ffmpeg视频解码原理和实战-(2)对avpacket中的数据进行解码并防止丢帧

源文件:

cpp 复制代码
#include <iostream>
#include <fstream>
using namespace std;
extern "C" { //指定函数是c语言函数,函数名不包含重载标注
//引用ffmpeg头文件
#include <libavcodec/avcodec.h>
}
//预处理指令导入库
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
int main(int argc, char* argv[])
{
    //1 分割h264 存入AVPacket
      // ffmpeg -i v1080.mp4 -s 400x300 test.h264
    string filename = "test.h264";
    ifstream ifs(filename, ios::binary);
    if (!ifs)return -1;
    unsigned char inbuf[4096] = { 0 };//用于存储h264编码流
    AVCodecID codec_id = AV_CODEC_ID_H264;


    //1 找解码器
    auto codec = avcodec_find_decoder(codec_id);

    //2 创建解码器上下文
    auto c = avcodec_alloc_context3(codec);

    //3 打开上下文
    avcodec_open2(c, NULL, NULL);


    //分割上下文
    auto parser = av_parser_init(codec_id);
    auto pkt = av_packet_alloc();
    auto frame = av_frame_alloc();
    while (!ifs.eof())
    {
        ifs.read((char*)inbuf, sizeof(inbuf));//将h264编码的流读入inbuf中,一次读4096
        int data_size = ifs.gcount();// 读取的字节数,inbuf中的字节数
        if (data_size <= 0)break;
        auto data = inbuf;
        while (data_size > 0) //一次有多帧数据
        {
         
            //通过0001 截断输出到AVPacket 返回帧大小
            int ret = av_parser_parse2(parser, c,
                &pkt->data, &pkt->size, //截断后输出到AVpacket的data中
                data, data_size,        //h264编码流,待处理数据
                AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0
            );//返回消耗的输入数据字节数ret。如果所有输入数据都被消耗,则返回值等于 buf_size。如果解析过程中出现错误,则返回负数。
            data += ret;//data指针向前移动 ret个字节,继续处理inbuf未处理的数据
            data_size -= ret; //待处理的数据大小
            if (pkt->size)
            {
                //cout << pkt->size << " "<<flush;
                //发送packet到解码线程
                ret = avcodec_send_packet(c, pkt);//把avpacket给解码器进行解码
                if (ret < 0)
                    break;
                //获取多帧解码数据
                while (ret >= 0)
                {
                    //每次回调用av_frame_unref 
                    ret = avcodec_receive_frame(c, frame);//拿到解码后的数据
                    if (ret < 0)
                        break;
                    cout << frame->format << " " << flush;
                }
            }
        }
    }
    ///取出缓存数据,防止丢帧
    int ret = avcodec_send_packet(c, NULL);
    while (ret >= 0)
    {
        ret = avcodec_receive_frame(c, frame);
        if (ret < 0)
            break;
        cout << frame->format << "-" << flush;
    }
    av_parser_close(parser);
    avcodec_free_context(&c);
    av_frame_free(&frame);
    av_packet_free(&pkt);

    getchar();
    return 0;
}
相关推荐
ai产品老杨2 小时前
解锁仓储智能调度、运输路径优化、数据实时追踪,全功能降本提效的智慧物流开源了
javascript·人工智能·开源·音视频·能源
MThinker2 小时前
02-Media-8-uvc_with_csc.py 使用硬件解码的USB摄像头(UVC)捕获视频并显示的程序
音视频·智能硬件·micropython·canmv·k230
向阳花开_miemie2 小时前
Android音频学习(十八)——混音流程
学习·音视频
清风66666612 小时前
基于STM32的APP遥控视频水泵小车设计
stm32·单片机·mongodb·毕业设计·音视频·课程设计
Cary丿Xin14 小时前
Luma 视频生成 API 对接说明
音视频
简鹿办公18 小时前
FFmpeg vs 去水印软件:哪种方式更适合你?
ffmpeg·怎样去除视频水印·如何去视频logo视频水印
奔跑吧 android1 天前
【车载audio开发】【基础概念1】【音频基础概念通俗讲解】
音视频·channel·audio·aosp·frame·period_size
小狮子安度因1 天前
ffplay数据结构分析
数据结构·ffmpeg
小狮子安度因1 天前
ffplay音频重采样
ffmpeg·音视频
张晓~183399481212 天前
短视频矩阵源码-视频剪辑+AI智能体开发接入技术分享
c语言·c++·人工智能·矩阵·c#·php·音视频