FFmpeg - 视频解码过程
2012-07-02 15:58
155 查看
FFmpeg的文档做得不好,导致学会使用这个库是存在一定难度的。在对文件进行解码时,抄网上流传的例子就可以了。比如,常见的例子是这样的:
以解TS流文件为例,上述代码会把读文件、读TS包、解PMT, PAT、解PES等过程都内部做了,使用者即使不懂这些概念,也是可以写出一个解TS文件成图像的例子的。但如果输入的是一个TS流怎么办呢?--显然再用av_open_input_file()这种就行了。
对于流媒体TS,要对MPEG-2有一定了解。其步骤简述如下:
(1) 解复用,得到PAT, PMT,得到PES_pid
(2) 对PES解复用,得到其PTS和ES
(3) 把ES(图像编码数据)交给FFmpeg解码,得到图像
(4) 按PTS顺序,显示图像。如果是AVC/H264编码,其PTS顺序一般不是自然顺序。
那么,在第(3)步中,怎么使用FFmpeg来解ES呢?参考其examples,总结得到以下顺序:
////////////////////初始化 ///////////////////////////////
//////////// 解码 /////////////////
main(0 { av_register_all(); // Open video file if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0) return -1; // Couldn't open file // Retrieve stream information if(av_find_stream_info(pFormatCtx)<0) return -1; // Couldn't find stream information pCodecCtx=&pFormatCtx->streams[videoStream]->codec; // Find the decoder for the video stream pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) return -1; // Codec not found ... }
以解TS流文件为例,上述代码会把读文件、读TS包、解PMT, PAT、解PES等过程都内部做了,使用者即使不懂这些概念,也是可以写出一个解TS文件成图像的例子的。但如果输入的是一个TS流怎么办呢?--显然再用av_open_input_file()这种就行了。
对于流媒体TS,要对MPEG-2有一定了解。其步骤简述如下:
(1) 解复用,得到PAT, PMT,得到PES_pid
(2) 对PES解复用,得到其PTS和ES
(3) 把ES(图像编码数据)交给FFmpeg解码,得到图像
(4) 按PTS顺序,显示图像。如果是AVC/H264编码,其PTS顺序一般不是自然顺序。
那么,在第(3)步中,怎么使用FFmpeg来解ES呢?参考其examples,总结得到以下顺序:
////////////////////初始化 ///////////////////////////////
// 查找解码器ID CodecID codec_id = CODEC_ID_NONE; switch(stream_type) { default: codec_id = CODEC_ID_H264; } // 查找解码器 m_pCodec = avcodec_find_decoder(codec_id); if (!m_pCodec) { fprintf(stderr, "codec not found\n"); return -1; } // 打开解码器 m_pCodecContext = avcodec_alloc_context(); if (avcodec_open(m_pCodecContext, m_pCodec) < 0) { fprintf(stderr, "could not open codec\n"); return -1; } // 申请一帧的空间用于解码 m_pPicture = avcodec_alloc_frame();
//////////// 解码 /////////////////
// 解析PES得到ES TS_PesDecoder pesdec; pesdec.Parse(m_iDemux.Payload(), m_iDemux.PayloadSize()); // AVPacket应包含的是ES数据 AVPacket avpkt; av_init_packet(&avpkt); avpkt.size = pesdec.m_nEsLength; avpkt.data = pesdec.m_pEs; if (avpkt.size == 0) return -1 ; // 解AVPacket,得到图像数据AVFrame while (avpkt.size > 0) { int got_picture = 0; int len = avcodec_decode_video2(m_pCodecContext, m_pPicture, &got_picture, &avpkt); if (len < 0) { fprintf(stderr, "Error while decoding frame...\n"); break; } if (got_picture) { int width = m_pCodecContext->width; int height = m_pCodecContext->height; VideoFrame frame; frame.nWidth = width; frame.nHeight = height; frame.nPts = pesdec.m_nPts / 45; // in ms AVPicture& pic_rgb = frame.iPic; avpicture_alloc(&pic_rgb, PIX_FMT_RGB24, width, height); // 用swscale库把YUYV420P转成RGB24 SwsContext* img_convert_ctx = sws_getContext(width, height, PIX_FMT_YUV420P, width, height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(img_convert_ctx, m_pPicture->data, m_pPicture->linesize, 0, height, pic_rgb.data, pic_rgb.linesize); sws_freeContext(img_convert_ctx); printf("Saving a frame ....\n"); m_iMutex.Lock(); m_lstFrames.push_back(frame); m_iMutex.Unlock(); return 1; } avpkt.size -= len; avpkt.data += len; }
相关文章推荐
- 图像视频编码和FFmpeg(5)-----FFmpeg关键结构体的关系和编解码的基本过程
- Linux/Windows 下分别编译音视频编解码库ffmpeg的流程和注意事项
- 利用ffmpeg做视频解码的顺序
- 音视频开发——ffmpeg解码(四)
- android studio 2.2 cmake ffmpeg 简单的播放器(这里只有视频解码)
- Android本地视频播放器开发--ffmpeg解码视频文件中的音频(1)
- 基于FFMPEG 的跨平台视频编解码研究
- FFMPEG学习----解码视频
- ffmpeg / avconv是通用的视频/音频编解码命令行工具【转】
- ffmpeg视频播放过程
- Android音视频学习第2章:使用ffmpeg进行音频解码
- ffmpeg解码视频存为BMP文件
- 视频编解码,FFMPEG,RTP问题汇总
- FFMPEG解码过程
- 利用ffmpeg和opencv进行视频的解码播放
- 学习FFmpeg API – 解码视频
- (转)利用ffmpeg来进行视频解码的完整示例代码(H.264)
- 利用ffmpeg和opencv进行视频的解码播放
- 2017.10.27开始学习FFMPEG音视频编解码,通过学习雷霄骅文章
- FFMpeg对视频文件进行解码的大致流程