[FFmpeg]在.MP4文件中提取.264(解封装)

本文详细描述了如何使用FFmpeg工具解封装.mp4文件并转换为H.264格式,包括打开文件、获取流信息、初始化packet、使用BSF进行编码转换和写入输出文件的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概要

本文主要是对.mp4进行解封装生成.264文件,使用ffplay进行播放。

/*指令提取 ffmpeg -i output.mp4 -an -vcodec copy -bsf: h264_mp4toannexb out.h264*/

整体架构流程

  • 打开媒体文件(.mp4文件)                                   avformat_open_input
  • 获取码流信息                                                    avformat_find_stream_info
  • 获取视频流                                                        av_find_best_stream
  • 初始化packet(开始读取)                               av_init_packet
  • 读取packet数据                                                 av_read_frame
  • 释放packet资源                                                 av_packet_unref
  • 关闭媒体文件                                                     avformat_close_input

代码

    const char* infilename  = "/home/16THDD/xieyingbo/xieyingbo/big_buck_bunny.mp4";
    const char* outfilename = "/home/16THDD/xieyingbo/xieyingbo/output.264";
    //1.打开媒体文件(.mp4文件) avformat_open_input
    av_register_all();
    AVFormatContext *pFormatCtx = NULL;
    int ret = avformat_open_input(&pFormatCtx, infilename, NULL, NULL);
    if(ret != 0)
    {
        std::cout << "open input format error." << std::endl;
        return;
    }

    //2.获取码流信息 avformat_find_stream_info
    ret = avformat_find_stream_info(pFormatCtx, NULL);
    if(ret < 0)
    {
        std::cout << "find stream error" << std::endl;
        avformat_close_input(&pFormatCtx);
        return;
    }

    //3.获取视频流 av_find_best_stream
    int videoIndex = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if(videoIndex < 0)
    {
        std::cout << "find best stream error" << std::endl;
        avformat_close_input(&pFormatCtx);
        return;
    }
    else
    {
        std::cout << "videoIndex = " << videoIndex << std::endl;
    }

    //4.初始化packet(开始读取)av_init_packet
    AVPacket packet;
    av_init_packet(&packet);
    const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
    if(bsf == NULL)
    {
        std::cout << "h264_mp4 to annexb error" << std::endl;
        avformat_close_input(&pFormatCtx);
        return;
    }
    AVBSFContext *bsfCtx = NULL;
    av_bsf_alloc(bsf, &bsfCtx);
    avcodec_parameters_copy(bsfCtx->par_in, pFormatCtx->streams[videoIndex]->codecpar);
    av_bsf_init(bsfCtx);

    //5.读取packet数据 av_read_frame
    FILE *ftp = fopen(outfilename, "wb");
    if(ftp == NULL)
    {
       std::cout << "open infilename error" << std::endl;
       avformat_close_input(&pFormatCtx);
       return;
    }
    while(av_read_frame(pFormatCtx, &packet) >= 0)
    {
        if(packet.stream_index == videoIndex)
        {
            if(av_bsf_send_packet(bsfCtx, &packet) == 0)
            {
                while(av_bsf_receive_packet(bsfCtx, &packet) == 0)  //不一定一次就能接收完
                {
                    if(fwrite(packet.data, 1, packet.size, ftp) != packet.size)
                    {
                        std::cout << "open infilename error" << std::endl;
                        fclose(ftp);
                        avformat_close_input(&pFormatCtx);
                        return;
                    }
                }
            }
        }
        //6.释放packet资源 av_packet_unref
        av_packet_unref(&packet);
    }
    //7.关闭媒体文件 avformat_close_input
    if(pFormatCtx)
    {
        avformat_close_input(&pFormatCtx);
    }

    if(ftp)
    {
        fclose(ftp);
    }

    if(bsfCtx)
    {
        av_bsf_free(&bsfCtx);
    }

 

小结

/home/16THDD/xieyingbo/xieyingbo/emobile_2023-11-29_13-28-46.png

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值