从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;
}
相关文章
|
5月前
|
存储 编解码
如何将BDMV文件转换为MKV或MP4?
许多拥有蓝光光驱的用户可能在电脑上存储了一些BDMV文件。虽然这些文件提供了高质量的视频和音频,但由于其文件格式的限制,它们可能无法在某些设备上播放。因此,将BDMV文件转换为常见的MKV或MP4文件就变得非常重要。本文将介绍一种简单而有效的方法来完成这个转换过程。
864 2
|
3天前
提取mp4中的音频Pkt,以adts的方式写为aac文件
使用FFmpeg库从MP4文件中提取音频流,并将其转换为带有ADTS头的AAC文件,提供了两种方法:位运算和位域操作。
10 1
|
Linux 计算机视觉 iOS开发
使用ffmpeg将MP4转换为WebM格式
使用ffmpeg将MP4转换为WebM格式
1485 2
|
存储 编解码 算法
MP4文件格式的解析,以及MP4文件的分割算法
MP4文件格式的解析,以及MP4文件的分割算法
160 0
|
存储 编解码 算法
MP4格式解析
MP4视频文件封装格式是基于QuickTime容器格式定义的,因此参考QuickTime的格式定义对理解MP4文件格式很有帮助。MP4文件格式是一个十分开放的容器,几乎可以用来描述所有的媒体结构,MP4文件中的媒体描述与媒体数据是分开的,并且媒体数据的组织也很自由,不一定要按照时间顺序排列,甚至媒体数据可以直接引用其他文件。同时,MP4也支持流媒体。MP4目前被广泛用于封装h.264视频和AAC音频,是高清视频的代表。MP4格式的官方文件后缀名是“.mp4”,还有其他的以mp4为基础进行的扩展或者是缩水版本的格式,包括:M4V, 3GP, F4V等。
283 0
|
编解码 自然语言处理 网络协议
MPEG-TS封装格式
MPEG-TS封装格式介绍及解释
312 0
|
存储 编解码 JSON
MP4封装格式
MP4封装格式介绍及解释,本文介绍 mp4 里面各种 box 的作用,包括 mdat box, moov box,mdhd box 等等。
393 0
|
编解码 Linux vr&ar
如何将mp3文件转pcma格式或PCM格式的wav文件
如何将mp3文件转pcma格式或PCM格式的wav文件
利用ffmpeg 转mp4 格式
脚本内容如下直接复制即可 命名 convert2MP4.bat [Asm] 纯文本查看 复制代码 ? 01 02 03 04 05 06 07 08 09 10 @echo off title 视频批量无损转mp4 set path=D:ffmpeg/bin/ffmpeg.exe;%path% for /f "delims=" %%i in ('dir /b /a-d /s "*.%1"') do echo ffmpeg -i "%%i" -y -qscale 0 -vcodec libx264 "%cd%\%%~ni.mp4" ping -n 5 127.0.0.
278 0