从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;
}
相关文章
|
6月前
|
存储 编解码
如何将BDMV文件转换为MKV或MP4?
许多拥有蓝光光驱的用户可能在电脑上存储了一些BDMV文件。虽然这些文件提供了高质量的视频和音频,但由于其文件格式的限制,它们可能无法在某些设备上播放。因此,将BDMV文件转换为常见的MKV或MP4文件就变得非常重要。本文将介绍一种简单而有效的方法来完成这个转换过程。
1007 2
|
15天前
|
编解码 算法 安全
flv 和 mp4 区别
【10月更文挑战第26天】FLV和MP4格式在容器格式、编码标准、视频质量、兼容性、流媒体支持以及编辑制作等方面都存在一定的区别。用户在选择使用哪种格式时,应根据具体的需求和应用场景来决定。如果注重网络流媒体播放和实时性,FLV格式可能更适合;如果追求更好的视频质量、广泛的兼容性和方便的编辑制作,MP4格式则是更好的选择。
|
1月前
提取mp4中的音频Pkt,以adts的方式写为aac文件
使用FFmpeg库从MP4文件中提取音频流,并将其转换为带有ADTS头的AAC文件,提供了两种方法:位运算和位域操作。
27 1
|
3月前
|
编解码 Shell Python
使用lame以多进程方式转码wav为mp3
使用lame以多进程方式转码wav为mp3
|
Linux 计算机视觉 iOS开发
使用ffmpeg将MP4转换为WebM格式
使用ffmpeg将MP4转换为WebM格式
1623 2
|
存储 编解码 算法
MP4文件格式的解析,以及MP4文件的分割算法
MP4文件格式的解析,以及MP4文件的分割算法
170 0
|
编解码 自然语言处理 网络协议
MPEG-TS封装格式
MPEG-TS封装格式介绍及解释
323 0
|
存储 编解码 JSON
MP4封装格式
MP4封装格式介绍及解释,本文介绍 mp4 里面各种 box 的作用,包括 mdat box, moov box,mdhd box 等等。
407 0
|
编解码 Linux vr&ar
如何将mp3文件转pcma格式或PCM格式的wav文件
如何将mp3文件转pcma格式或PCM格式的wav文件