FFmpeg - 视频解码过程
来源:互联网 发布:iphone6网络 ios10 编辑:程序博客网 时间:2024/05/01 15:56
FFmpeg的文档做得不好,导致学会使用这个库是存在一定难度的。在对文件进行解码时,抄网上流传的例子就可以了。比如,常见的例子是这样的:
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 - 视频解码过程
- ffmpeg视频解码分析
- FFmpeg解码音视频
- ffmpeg解码视频
- Qt+ffmpeg解码视频
- Qt + ffmpeg 视频解码
- FFmpeg -- 解码视频
- ffmpeg解码烂视频
- FFMPEG学习----解码视频
- ffmpeg视频解码分析
- FFMPEG 视频解码流程
- FFMPEG+Qt解码视频
- FFMPEG音视频解码
- FFMPEG 之视频解码
- FFMPEG解码过程
- ffmpeg 解码过程
- FFmpeg - 音频解码过程
- 基于ffmpeg解码h264视频
- 我很喜欢这个博客
- poj 3621(参数搜索+二分+spfa负环求解)
- FFmepg - 编译
- Android Tombstone/Crash的log分析和定位
- 读取的GPS数据为乱码
- FFmpeg - 视频解码过程
- 学摄影:三分钟了解直方图
- 求子数组的最大和
- 字符串转Ascii码与Ascii码转字符串
- 共轭检验
- 敏捷软件开发 Agile Software Development
- Unity界面插件NGUI核心组件说明
- uboot 环境变量例子
- 在Android上使用ZXing识别条码/二维码