关于ffmpeg编解码问题

fangext520 2013-08-21 09:49:35
/*******************************************************************************************/
int test1(JNIEnv* env,jstring str)
{
AVFormatContext *pFormatCtx;
int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameRGB;
AVPacket packet;
int frameFinished;
int numBytes;
uint8_t *buffer;
struct SwsContext *img_convert_ctx;
int stream_index;
jbyte* stream_index_byte;
jbyte* videostream;
av_register_all();
avformat_network_init();
int open_url_error_flag;
int stream_info;
int open_codec_error ;
const jbyte* url ;
if(str == NULL)
return -1;
url = (*env)->GetStringUTFChars(env,str,NULL);
if(url == NULL)//转换路径有可能返回位null
return -1;
LOGE("test url %s",url);
open_url_error_flag = avformat_open_input(&pFormatCtx,url,NULL,NULL);
if(open_url_error_flag < 0)
return -1;
LOGE("open url error flag = %d",open_url_error_flag);
stream_info = avformat_find_stream_info(pFormatCtx,NULL);
LOGE("find stream info = %d",stream_info);
if(stream_info<0)
return -1;
av_dump_format(pFormatCtx,0,url,0);

// Find the first video stream
// 遍历文件的流,找到第一个视频流,并记录流的编码信息
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
{
videoStream=i;
break;
}
}
if(videoStream==-1)
return -1; // Didn't find a video stream

// Get a pointer to the codec context for the video stream
// 得到视频流编码的上下文指针
pCodecCtx=pFormatCtx->streams[videoStream]->codec;

// construct the scale context, conversing to PIX_FMT_RGB24
// 根据编码信息设置渲染格式
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
if(img_convert_ctx == NULL)
{
fprintf(stderr, "Cannot initialize the conversion context!\n");
// exit(1);
return -1;
}

// Find the decoder for the video stream
// 在库里面查找支持该格式的解码器
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
{
fprintf(stderr, "Unsupported codec!\n");
return -1; // Codec not found
}
// Open codec
// 打开解码器
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
return -1; // Could not open codec

// Allocate video frame
// 分配一个帧指针,指向解码后的原始帧
pFrame=avcodec_alloc_frame();

// Allocate an AVFrame structure
// 分配一个帧指针,指向存放转换成rgb后的帧
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
return -1;

// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); // buffer = new uint8_t[numBytes];

// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
// 给pFrameRGB帧附加上分配的内存
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);

// Read frames and save first five frames to disk
i=0;
while(av_read_frame(pFormatCtx, &packet)>=0) // 读取一个帧
{
LOGE("packet.stream_index = %d",packet.stream_index);
LOGE("videoStream = %d",videoStream);
// stream_index_byte = intToByte(packet.stream_index);
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
// Decode video frame
// 解码该帧
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
// Did we get a video frame?
if(frameFinished)
{
// Convert the image from its native format to RGB
// img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,
// (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width,
// pCodecCtx->height);

// 把该帧转换成rgb

// 如果只提取关键帧,加上这句
// if (pFrame->key_frame == 1)
sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Save the frame to disk
// 保存前5帧
if(++i<=5)
{
// char pic[200];
// sprintf(pic,"pic%d.bmp",i);
// av_create_bmp(pic, pFrameRGB->data[0], pCodecCtx->width, pCodecCtx->height, 24);
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
}
}
}

// Free the packet that was allocated by av_read_frame
// 释放读取的帧内存
av_free_packet(&packet);
}

// Free the RGB image
av_free(buffer);
av_free(pFrameRGB);

// Free the YUV frame
av_free(pFrame);

// Close the codec
avcodec_close(pCodecCtx);

// Close the video file
av_close_input_file(pFormatCtx);

return 0;
}

这是我从网上拷贝的代码,然后改了一些方法,因为我用的是2.0的所以有些方法改变了,现在有一个问题就是 packet.stream_index==videoStream他们的值不一致,packet.stream_index 一直是一个7位数,我不清楚这是为啥。。是字节序的原因么?
...全文
64 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
fangext520 2013-08-21
  • 打赏
  • 举报
回复
额。。怎么VS断点额。。之前以为是字节序的问题。。放到同事那测了下可以的。。发现是头文件太老了。。
南瓜饼 2013-08-21
  • 打赏
  • 举报
回复
你用VS断点走啊 你这样猜什么时候能才出来呢
媒体盒子 2013-08-21
  • 打赏
  • 举报
回复
建议把参数都打印出来看是哪一步出错,pFormatCtx->nb_streams可以看看是几

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧