ffmpeg解码核心代码理解
将一个视频文件解压转为位YUV文件的代码理解:
final conclusion --- 解码核心总结:
1. 将总媒体结构体AVFormatContext读到AVPacket里面去 --- av_read_frame(AVFrameContext *, AVPacket *); 一次读一帧
2. 判断读取后的数据是否是视频流, AVPacket->stream_index是否等于我们前面判断的video_index(AVFormatContext->stream[video_index]),是的话就可以进行解码
3. 将AVPacket的压缩数据加压到AVFrame,avcodec_decodec_video2(AVCodecContext *,AVFrame*,int *,AVPacket*);
//参数依次为:
// param.1 该视频流对应的解码器上下文结构体 AVCodecContext = AVFormatContext->streams[videoIndex]->codec;
// param.2 解码后存放数据的AVFrame,用av_frame_alloc()为其分配内存,记住最后要用av_frame_free(&AVFrame)释放内存
// param.3 got_picture标志位, 成功执行并且获得数据后非0
// param.4 上一步获得的数据
4. 获得解压后的图片数据后,需要像素转换或者拉伸的,将一个AVFrame --> other AVFrame;用sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
// param.1 SwsContext* -- image_convert_ctx,用sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P(视频格式), SWS_BICUBIC(拉伸或者压缩的算法), NULL, NULL, NULL);初始化该结构体,最后也>要用sws_freeContext(img_convert_ctx);释放
// param.2 处理前的数据源
// param.3 每一个data的宽,不一定等于AVFrame.width
// param.4 不理解
// 后面2个就是目标的数据了
5. 将数据写入文件size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
y_size=pCodecCtx->width*pCodecCtx->height; //总数据量大小
fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Y YUV视频依次存放在data[0] [1] [2] 里面
fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //U
fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V
6. 最后记住释放之前分配的内存即可
源代码工程请查看我的资源FFmpegDecoder