求高手帮助,关于视频文件得到视频帧数据问题
各位高手,大家好。我是一个android新手,原来也没有怎么接触过多媒体方面的知识,我想问下在android 2.0下如何解析h.264 的视频文件得到视频帧数据。 --------------------编程问答-------------------- 有高手解答下嘛。。小弟跪谢~~ --------------------编程问答-------------------- 这个你要看opencore了 --------------------编程问答--------------------从什么地方入手呢,我查了下opencore是基于C++的。。小弟只想用android提供的api来干这件事情。 --------------------编程问答-------------------- 这是一个解析本地h.264并播放的例子,希望对你有帮助。看不懂的可以先学习h.264的相关概念,http://hi.baidu.com/sdlyfdy/blog/category/h.264
--------------------编程问答--------------------
public class H264Android extends Activity {
VView vv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
vv = new VView(this);
setContentView(vv);
}
// Menu item Ids
public static final int PLAY_ID = Menu.FIRST;
public static final int EXIT_ID = Menu.FIRST + 1;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, PLAY_ID, 0, R.string.play);
menu.add(0, EXIT_ID, 1, R.string.exit);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case PLAY_ID:
{
String file = "/sdcard/352x288.264";
vv.PlayVideo(file);
return true;
}
case EXIT_ID:
{
finish();
return true;
}
}
return super.onOptionsItemSelected(item);
}
}
class VView extends View implements Runnable{
Bitmap mBitQQ = null;
Paint mPaint = null;
Bitmap mSCBitmap = null;
int width = 352;
int height = 288;
byte [] mPixel = new byte[width*height*2];
ByteBuffer buffer = ByteBuffer.wrap( mPixel );
Bitmap VideoBit = Bitmap.createBitmap(width, height, Config.RGB_565);
int mTrans=0x0F0F0F0F;
String PathFileName;
public native int InitDecoder(int width, int height);
public native int UninitDecoder();
public native int DecoderNal(byte[] in, int insize, byte[] out);
static {
System.loadLibrary("H264Android");
}
public VView(Context context) {
super(context);
setFocusable(true);
int i = mPixel.length;
for(i=0; i<mPixel.length; i++)
{
mPixel[i]=(byte)0x00;
}
}
public void PlayVideo(String file)
{
PathFileName = file;
new Thread(this).start();
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
VideoBit.copyPixelsFromBuffer(buffer);
canvas.drawBitmap(VideoBit, 0, 0, null);
}
int MergeBuffer(byte[] NalBuf, int NalBufUsed, byte[] SockBuf, int SockBufUsed, int SockRemain)
{
int i=0;
byte Temp;
for(i=0; i<SockRemain; i++)
{
Temp =SockBuf[i+SockBufUsed];
NalBuf[i+NalBufUsed]=Temp;
mTrans <<= 8;
mTrans |= Temp;
if(mTrans == 1) {
i++;
break;
}
}
return i;
}
public void run()
{
InputStream is = null;
FileInputStream fileIS=null;
int iTemp=0;
int nalLen;
boolean bFirst=true;
boolean bFindPPS=true;
int bytesRead=0;
int NalBufUsed=0;
int SockBufUsed=0;
byte [] NalBuf = new byte[40980];
byte [] SockBuf = new byte[2048];
try
{
fileIS = new FileInputStream(PathFileName);
}
catch(IOException e)
{
return ;
}
InitDecoder(width, height);
while (!Thread.currentThread().isInterrupted())
{
try
{
bytesRead = fileIS.read(SockBuf, 0, 2048);
}
catch (IOException e) {}
if(bytesRead<=0)
break;
SockBufUsed =0;
while(bytesRead-SockBufUsed>0)
{
nalLen = MergeBuffer(NalBuf, NalBufUsed, SockBuf, SockBufUsed, bytesRead-SockBufUsed);
NalBufUsed += nalLen;
SockBufUsed += nalLen;
while(mTrans == 1)
{
mTrans = 0xFFFFFFFF;
if(bFirst==true) {
bFirst = false;
}
else {
if(bFindPPS==true) {
if( (NalBuf[4]&0x1F) == 7 )
{
bFindPPS = false;
}
else
{
NalBuf[0]=0;
NalBuf[1]=0;
NalBuf[2]=0;
NalBuf[3]=1;
NalBufUsed=4;
break;
}
}
iTemp=DecoderNal(NalBuf, NalBufUsed-4, mPixel);
if(iTemp>0)
postInvalidate(); }
NalBuf[0]=0;
NalBuf[1]=0;
NalBuf[2]=0;
NalBuf[3]=1;
NalBufUsed=4;
}
}
}
try{
if(fileIS!=null)
fileIS.close();
if(is!=null)
is.close();
}
catch (IOException e) {
e.printStackTrace();
}
UninitDecoder();
}
}
--------------------编程问答-------------------- 来人帮忙啊~~ --------------------编程问答-------------------- 我想到一个思路,我看了下摄像头录制视频的时候,很容易就可以提取每帧数据,通过实现PreviewCallback的onPreviewFrame方法。那么请问大家知不知道在播放视频时,是否也有相应的回调接口有类似这样功能的方法来获取每帧数据呢? --------------------编程问答-------------------- 我还想到一种办法,如果利用局部截屏是否可行呢。。各位高手们,帮帮忙。。。
/*
* Class: h264_VView
* Method: InitDecoder
* Signature: ()I
*/
jlong Java_h264_VView_InitDecoder(JNIEnv* env, jobject thiz)
{
CreateYUVTab_16();
Decoder * de = (Decoder *)av_malloc(sizeof(Decoder));
de->c = avcodec_alloc_context();
avcodec_open(de->c);
de->picture = avcodec_alloc_frame();//picture= malloc(sizeof(AVFrame));
return (jlong)de;
}
/*
* Class: h264_VView
* Method: UninitDecoder
* Signature: ()I
*/
jint Java_h264_VView_UninitDecoder(JNIEnv* env, jobject thiz,jlong pDecoder)
{
DeleteYUVTab();
if (pDecoder)
{
Decoder * de=(Decoder * )pDecoder;
if(de->c)
{
decode_end(de->c);
free(de->c->priv_data);
free(de->c);
de->c = NULL;
}
if(de->picture)
{
free(de->picture);
de->picture = NULL;
}
free(de);
return 1;
}
else
return 0;
}
/*
* Class: h264_VView
* Method: DecoderNal
* Signature: ([B[I)I
*/
jint Java_h264_VView_DecoderNal(JNIEnv* env, jobject thiz,jlong pDecoder,jbyteArray in, jint nalLen, jbyteArray out)
{
int i;
int imod;
int got_picture;
if (pDecoder)
{
Decoder * de=(Decoder * )pDecoder;
jbyte * Buf = (jbyte*)(*env)->GetByteArrayElements(env, in, 0);
jbyte * Pixel= (jbyte*)(*env)->GetByteArrayElements(env, out, 0);
int consumed_bytes = decode_frame(de->c, de->picture, &got_picture, Buf, nalLen);
if(consumed_bytes > 0)
{
DisplayYUV_16((int*)Pixel, de->picture->data[0], de->picture->data[1], de->picture->data[2], de->c->width, de->c->height, de->picture->linesize[0], de->picture->linesize[1], de->c->width);
}
(*env)->ReleaseByteArrayElements(env, in, Buf, 0);
(*env)->ReleaseByteArrayElements(env, out, Pixel, 0);
return consumed_bytes;
}
else
return 0;
}
补充:移动开发 , Android