从mp4、flv、ts文件中提取出AVC(h264)

简介: 使用FFmpeg从mp4、flv、ts等封装格式的文件中提取AVC(H.264)视频流,并将其写入文件。

分别从封装格式为mp4、flv、ts文件中提取出AVC(h264)并写入文件

/*****************************************************************//**
 * \file   WriteAVC.cpp
 * \brief  提取视频中的视频流,写入为AVC(h264)文件
 * 
 * \author 13648
 * \date   April 2024
 *********************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#include "myLog.h"
#include <iostream>

extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavcodec/bsf.h>
}

#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avcodec.lib")

/**
 * 由于h264有两种格式,一种mp4格式(不带startcode,sps,pps信息)一种annexb格式(带startcode,sps、pps信息)
 * 但是大多数的编解码器只支持annexb格式pkt数据,
 * 因此在处理mp4或者flv格式的文件时需要使用h264_mp4toannexb比特流过滤器处理
 */
int main()
{
    AVFormatContext* ifmt_ctx = NULL;
    const std::string in_filename = "./MediaFile/input_5s.flv";        // input_5s.flv input_5s.ts

    int nRet = avformat_open_input(&ifmt_ctx, in_filename.c_str(), NULL, NULL);
    if (nRet != 0)
    {
        LOG_WARNING("avformat_open_input error\n");
        return -1;
    }

    nRet = avformat_find_stream_info(ifmt_ctx, NULL);
    if (nRet < 0)
    {
        LOG_WARNING("avformat_find_stream_info faild\n");
        avformat_close_input(&ifmt_ctx);
        return -2;
    }

    int video_idx = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if (video_idx < 0)
    {
        LOG_WARNING("avformat_find_stream_info faild\n");
        avformat_close_input(&ifmt_ctx);
        return -3;
    }

    const std::string out_filename = "./MediaFile/input_5s.h264";
    FILE* out_fp = fopen(out_filename.c_str(), "wb");
    if (!out_fp)
    {
        LOG_WARNING("open out_filename faild\n");
        avformat_close_input(&ifmt_ctx);
        return -4;
    }

    // 获取比特流过滤器
    const AVBitStreamFilter* bsfilter = av_bsf_get_by_name("h264_mp4toannexb");
    AVBSFContext* bsf_ctx = NULL;
    // 初始化比特流过滤器
    av_bsf_alloc(bsfilter, &bsf_ctx);
    // 给过滤器上下文添加解码器属性
    avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[video_idx]->codecpar);
    av_bsf_init(bsf_ctx);

    AVPacket* pkt = av_packet_alloc();
    pkt->data = NULL;
    pkt->size = 0;
    while (true)
    {
        nRet = av_read_frame(ifmt_ctx, pkt);
        if (nRet < 0)
        {
            LOG_WARNING("av_read_frame file finish\n");
            break;
        }
        if (nRet == 0 && pkt->stream_index == video_idx)
        {
#if 1
            if (av_bsf_send_packet(bsf_ctx, pkt) != 0)    // 发送包到比特流过滤器添加startcode、sps、pps信息
            {
                av_packet_unref(pkt);
                continue;
            }
            av_packet_unref(pkt);                // 清除,下面使用这个pkt接收bsf处理后的包
            while (av_bsf_receive_packet(bsf_ctx, pkt) == 0)    // 添加sps pps后可能不止一个包
            {
                size_t writeLen = fwrite(pkt->data, 1, pkt->size, out_fp);
                if (writeLen != pkt->size)
                {
                    LOG_WARNING("write pkt error\n");
                }
                fflush(out_fp);
                av_packet_unref(pkt);
            }
#else
            // 如果是ts流(自带sps pps信息,可以直接写入)
            size_t writeLen = fwrite(pkt->data, 1, pkt->size, out_fp);
            if (writeLen != pkt->size)
            {
                LOG_WARNING("fwrite pkt error\n");
            }
            av_packet_unref(pkt);
#endif
        }
        else if(nRet == 0) 
        {
            av_packet_unref(pkt);
        }
    }

    if (pkt)
    {
        av_packet_free(&pkt);
    }
    if (out_fp)
    {
        fclose(out_fp);
    }
    if (bsf_ctx)
    {
        av_bsf_free(&bsf_ctx);
    }
    if (ifmt_ctx)
    {
        avformat_close_input(&ifmt_ctx);
    }

    return 0;
}
相关文章
|
存储 搜索推荐 人机交互
Qt鼠标事件全面解析:从基础到实战
Qt鼠标事件全面解析:从基础到实战
2326 0
|
XML JSON 前端开发
dom4j - 使用详解与xml-json转换
dom4j - 使用详解与xml-json转换
270 1
|
IDE 编译器 Linux
linux 编译 c或cpp 文件为动态库 so 文件(最简单直观的模板)
linux 编译 c或cpp 文件为动态库 so 文件(最简单直观的模板)
|
6月前
|
人工智能 自然语言处理 搜索推荐
AI 搜索开放平台重磅发布:Qwen3 模型上线啦
阿里云AI搜索开放平台重磅发布最新Qwen3模型,为企业和开发者提供全栈智能搜索解决方案。Qwen3作为最新一代大模型,在推理、多语言支持和Agent能力上表现卓越。用户可通过三步快速体验Qwen3服务,助力业务在AI时代抢占先机。
651 13
|
4月前
|
监控 搜索推荐 数据挖掘
淘宝、京东、拼多多电商API接口对比
本文对比分析了淘宝、京东、拼多多三大电商平台的API接口。淘宝API数据全面、实时更新,适合商品信息展示与竞品分析;京东API在商品管理和数据分析方面表现突出,助力精细化运营;拼多多API融入社交元素,强调优惠券管理与用户关系分析。三者均支持实时数据更新,具备高稳定性和安全性,但易用性各有差异。开发者可根据需求选择合适的API,高效实现功能开发与数据利用,推动电商业务发展。
|
12月前
|
API
FFmpeg中AVPacket、AVFrame结构的基本使用
FFmpeg中AVPacket和AVFrame结构的内存分配、释放和引用计数处理,以及如何避免内存泄漏。
308 3
|
12月前
|
C++
SDL基础使用03(渲染显示bmp图片)
如何使用SDL库在C++中创建窗口、加载BMP图片、创建纹理,并通过渲染器进行显示的完整过程。
122 2
|
12月前
easyX实现自由落体小球
本文介绍了使用easyX图形库实现自由落体小球的编程方法,包括匀速下落和加速下落,以及如何处理小球的反弹和边界条件。
157 0
easyX实现自由落体小球
|
网络协议 编译器 Go
揭秘!TCP、RPC、gRPC、HTTP大PK,谁才是网络通信界的超级巨星?一篇文章带你秒懂!
【8月更文挑战第25天】本文以教程形式深入对比了TCP、RPC、gRPC与HTTP这四种关键通信协议,并通过Go语言中的示例代码展示了各自的实现方法。TCP作为一种可靠的传输层协议,确保了数据的完整性和顺序性;RPC与gRPC作为远程过程调用框架,特别适合于分布式系统的函数调用与数据交换,其中gRPC在性能和跨语言支持方面表现出色;HTTP则是广泛应用于Web浏览器与服务器通信的应用层协议。选择合适的协议需根据具体需求综合考量。
890 0
|
前端开发 容器
CSS【详解】对齐 (含文本垂直对齐,文本水平对齐、单行文本垂直居中、多行文本垂直居中、6 种方案块级元素水平垂直居中 、7 种方案图片水平垂直居中、文本自适应对齐、图标和文本对齐,图片和文本对齐等)
CSS【详解】对齐 (含文本垂直对齐,文本水平对齐、单行文本垂直居中、多行文本垂直居中、6 种方案块级元素水平垂直居中 、7 种方案图片水平垂直居中、文本自适应对齐、图标和文本对齐,图片和文本对齐等)
671 0