FFmpeg从入门到牛掰(一):解复用(demux)讲解

嵌入式平台移植ffmpeg的mux和demux功能 在将FFmpeg移植到基于ARMv5TEJ架构的嵌入式平台上的过程中,我们遇到了系列挑战。这个过程不仅涉及到了选择合适的编译选项,还包括了如何解决由于硬件限制引起的问题。本篇博客旨在提供个全面的指南,总结我们的经验和解决方案,以帮助他人在类似环境中进行FFmpeg的移植和编译。 阅读详情

转载请注明出处:https://blog.csdn.net/impingo
项目地址:https://github.com/im-pingo/pingos

概念

从今天开始我准备开始出一个ffmpeg系列教程,希望通过此系列教程能帮助大家认识ffmpeg和在工作用的运用。

在开始之前,首先要弄清以下几个概念:

  • 容器(Container)

容器就是一种文件格式,比如flv、mkv、mp4等。包含下面5种流以及文件头信息。

  • 流(Stream)

是一种视频数据信息的传输方式,5种流:音频,视频,字幕,附件,数据。

  • 包(Packet)
    在ffmpeg中包代表已经编码好的一个单位的音频或者视频。

  • 帧(Frame)
    在ffmpeg中帧代表一幅静止的图像(yuv数据)或一些数量的音频采样。

  • 编解码器(Codec)

是对视频进行压缩或者解压缩,CODEC =ENCode (编码) +DECode(解码)

  • 复用/解复用(mux/demux)

把不同的流按照某种容器的规则放入容器,这种行为叫做复用(mux)
把不同的流从某种容器中解析出来,这种行为叫做解复用(demux)

为了更好理解以上概念,下面以h264+aac编码的flv文件转码为 h265+mp3编码的mp4文件为例,ffmpeg的处理流程是这样的:

flv文件
flv解复用器
音频包 aac
aac音频解码器
原始音频采样pcm
mp3音频编码器
音频包mp3
视频包 h264
h264视频解码器
原始视频数据yuv
h265视频编码器
视频包 h265
mp4复用器
mp4文件

解复用操作

函数调用流程

最新的ffmpeg API接口不再需要 av_register_all()函数提前注册。
在这里插入图片描述

创建avformat上下文(可选,用avformat_open_input函数也可创建)

AVFormatContext* avformat_alloc_context()

结束时必须使用avformat_free_context()销毁AVFormatContext指针

打开输入文件

int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);

该函数作用是打开一个输入流(或者文件)并且读取媒体头信息(如音视频编码类型等等)。
任务结束时使用函数 avformat_close_input()关闭。

参数描述
ps指向AVFormatContext的指针,可以用avformat_alloc_context()提前申请,当然也可直接用avformat_open_input函数生成,不论哪种方式,都必须使用avformat_free_context()销毁该指针
url要打开的媒体流地址(或文件路径)
fmt输入类型,如果此参数不为空,则强制设置输入媒体的类型(如flv、mp4等)
options可选的选项,此处参考ffmpeg命令行操作里的一些输入参数,如reorder_queue_size、stimeout、scan_all_pmts 等等。使用av_dict_set()函数设置,使用av_dict_free()释放。

返回值 0 成功,失败则返回 AVERROR 负值

读取流信息

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)

读取媒体文件的数据包以获取流信息。 这个对于没有header的文件格式(例如MPEG)很有用。 总之使用该函数可以将输入流(文件)中的媒体信息(包括编码信息)解析出来。通过ic->streams[i]访问,streams的个数由ic->nb_streams获取。

读取音视频包

int av_read_frame(AVFormatContext *s, AVPacket *pkt);

将输入文件或输入URL的流内容读取到AVPacket中,关于AVPacket的字段含义,请参考以下代码中的日志输出。

解复用示例代码

#ifdef __cplusplus
extern "C" {
#endif
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#ifdef __cplusplus
}
#endif

static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt, const char *tag)
{
    AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;

    printf("%s: pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
           tag,
           av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),
           av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),
           av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),
           pkt->stream_index);
}

int main(int argc, char **argv)
{
    AVFormatContext *ifmt_ctx = NULL;
    AVPacket pkt;
    const char *in_filename;
    int ret, i;
    int stream_index = 0;
    int *stream_mapping = NULL;
    int stream_mapping_size = 0;

    if (argc < 2) {
        printf("usage: %s input\n"
               "API example program to remux a media file with libavformat and libavcodec.\n"
               "\n", argv[0]);
        return 1;
    }

    in_filename  = argv[1];

    if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
        fprintf(stderr, "Could not open input file '%s'", in_filename);
        goto end;
    }

    if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
        fprintf(stderr, "Failed to retrieve input stream information");
        goto end;
    }

    av_dump_format(ifmt_ctx, 0, in_filename, 0);

    stream_mapping_size = ifmt_ctx->nb_streams;
    stream_mapping = av_mallocz_array(stream_mapping_size, sizeof(*stream_mapping));
    if (!stream_mapping) {
        ret = AVERROR(ENOMEM);
        goto end;
    }

    for (i = 0; i < ifmt_ctx->nb_streams; i++) {
        AVStream *in_stream = ifmt_ctx->streams[i];
        AVCodecParameters *in_codecpar = in_stream->codecpar;

        if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
            in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
            in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
            stream_mapping[i] = -1;
            continue;
        }

        stream_mapping[i] = stream_index++;
    }

    while (1) {
        AVStream *in_stream;

        ret = av_read_frame(ifmt_ctx, &pkt);
        if (ret < 0)
            break;

        in_stream  = ifmt_ctx->streams[pkt.stream_index];
        if (pkt.stream_index >= stream_mapping_size ||
            stream_mapping[pkt.stream_index] < 0) {
            av_packet_unref(&pkt);
            continue;
        }

        pkt.stream_index = stream_mapping[pkt.stream_index];
        log_packet(ifmt_ctx, &pkt, "in");

        av_packet_unref(&pkt);
    }

end:

    avformat_close_input(&ifmt_ctx);

    /* close output */
    av_freep(&stream_mapping);

    if (ret < 0 && ret != AVERROR_EOF) {
        fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
        return 1;
    }

    return 0;
}

在这里插入图片描述

QQ交流群:697773082

ffmpegdemux流程简析 只是简单说说,没太多深入。 【avformat_open_input 流程】 这里我只说根据字节流来分析的过程,而不管扩展名啊什么的。 1、如果没申请,它会内部调用avformat_alloc_context帮你申请结构体; 2、如果有io的pb,它会自动加上AVFMT_FLAG_CUSTOM_IO这个flag; 3、然后调用init_input,这个执行probe,也就是获取到if 阅读详情

相关推荐

Simulink常用模块库(Bus与Mux)

汽车热管理系统工程师必备技能之——matlab/Simulink部分03——Bus/Mux/Demux介绍

m0_64651092的博客 2万+

Simulink仿真模块 - Demux

Demux:提取并输出虚拟向量信号的元素 在仿真库中的位置为: Simulink / Commonly Used Blocks Simulink / Signal Routing HDL Coder / Commonly Used Blocks HDL Coder / Signal Routing 模型为: 说明 Demux模块提取输入向量信号的分量,再将它们输出为单独的信号。输出信号端口从上到下排列。有关创建和分解向量的信息,参考复路信号。 实例...

jk_101的博客 3624

ffmpeg学习之路(Demux过程(解复用)1

篇文章说了下媒体文件解码的流程,在该基础上再对其中的第个过程Demuxffmpeg中是如何实现的进行说明。 ffmpeg中用来进行Demux的关键函数是avformat_open_input,这里先贴下源码中的定义: 头文件:avformat.h /** * Open an input stream and read the header. The codecs are not

开启技术人生 3403

FFMpeg example:封装和解封装demux

(1)使用bitstream filter处理每个AVPacket(简单) 把每个AVPacket中的数据(data字段)经过bitstream filter“过滤”遍。 关键函数是av_bitstream_filter_filter()。示例代码如下。 AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb"); while(av_read_frame(ifmt_ctx, &pk...

fdsafwagdagadg6576的专栏 1450

2 常见模块库(2)

simulink学习笔记,常见模块库~

m0_53316604的博客 3980

基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux

前面章中我们介绍了如何使用 conan 和 cmake 搭建 ffmpeg 运行环境,你做的还顺利吗?如果遇到任何问题,请在进行评论,我看到都会回复的。从本章开始,将正式开始我们的 ffmpeg 播放器学习之旅。接下去的任务是:使用 ffmpeg 解码视频,并将解码后的视频帧保存在本地(就像对视频截图样)。其中涉及到两个重要的知识点:解封装和视频解码。今天我们先聊解封装。此外,还会扩展 ffmpeg api 以及编解码相关的知识。本文参考文章来自。

记录学习的过程 2507

FFmpeg入门牛掰(二):转封装(remux)讲解

转载请注明出处:https://blog.csdn.net/impingo 项目地址:https://github.com/im-pingo/pingos 转封装讲解转封装流程函数调用流程函数接口代码示例QQ交流群:697773082 承接上篇文章,这里进行封装过程的讲解,如果对解复用(解封装)过程不了解的人请先阅读上篇文章(FFmpeg入门牛掰):解复用(demux)讲解) ,此篇文章...

impingo的博客 2083

关于音视频的些知识(demux、filter等)

MUX和DEMUX Mux 是 Multiplex 的缩写,意为“多路传输”,其实就是“混流”、“封装”的意思,与“合成”的意思相似就是指把视频素材和音频素材封装到个单独的文件中。muxing 是在mux 后面加了 -ing 构成的动名词形式。 Demux是在 mux 前面加了个表示否定的 De- 前缀,意思是进行与 muxing 相反的“分解复用”操作,也就是我们平时说的“分离”个文件中的视频部分或是音频部分。同样,也可以在 demux 后面加 -ing 构成动名词 demuxing。 意义:

顺其自然~专栏 2133

demux和mux基础理解

说人话的话,那就是从理解的角度看,mux就是融合数据或复合数据,demux就是分离复合数据。开源项目里常把demux或者mux作为前缀或者后缀,比如live555,ffmpeg等。其实还有种理解,mux就是多合,放到数学上叫“降维”。demux就是还原,分多。在流媒体里,mux被翻译成“复用”,demux被翻译成“解复用”。在数学软件(matlab等)或者流媒体开源项目里,常见到它们的身影。

huibin.yun的博客 1613

ffmpegdemux

今天学习解析媒体文件。 写了个用例,解析MP4文件得到视频帧和音频帧,并分别保存到不同的文件。 照惯例,先学习,再代码。 学习 av_register_all /** * 初始化 libavformat,并且注册所有的合并器、解析器和协议。 * 如果你不调用这个方法,你可以明确地选择你想要程序支持的格式。 * 参照 av_register_input_format() ...

Hi, Boy 4381

simulink中的mux与的demux

文章目录Question1. 代码与仿真图2 demux3 mux3.1 mux的使用顺序问题4 总结 Question 对Mux与demux的好奇。 1. 代码与仿真图 source.m中输出两个信号:xd=cos(t);与 yd=sin(t);,Source.m文件代码如下: %function [sys,x0,str,ts] = spacemodel(t,x,u,flag) function...

u013647759的博客 5万+

matlab demux,demux(demux用法)

mux1.多路转换器多路复用器多路复用 Multiple User Experiment 多用户实验网游 第九城市现正开发款名为《MUX》(奇迹传说)的MMORPG我在simpowersystems里的machines里面找到的Demux双击设置没这么多选项。demux个常见的模块,你直接在Simulink里面搜就可以了,般选第个。它这个模块拖到你的模型中后,把数量改成4就行了。希望采纳...

weixin_36212493的博客 1万+

多路分配器(解复用器)Demultiplexer 的类型分析

文章目录前言、Demultiplexer基本类型1. 1 to 2 Demultiplexer二、使用步骤1.引入库2.读入数据总结 前言 在数电中,我们都学过数据选择器(MUX),常用的有4选1数据选择器、8选1数据选择器,用于数据的选择切换,从组输入信号中选出指定的个送至输出端的组合逻辑电路,多输入输出,常见的形式是这个样子: 可是有的时候我们只有个输入,却需要这个输入根据输入地址代码的不同状态来对应不同的输出端口,这个时候就需要个特定的功能电路。 与数据选择器Multiplexer..

wonderful u 2万+

ffmpeg 问答系列->demux 部分

摘要:本文探讨了FFmpeg demux模块的工作原理,重点分析了MPEG-TS流处理过程。文章详细介绍了节目数量确定(通过SDT表)、流数量统计(通过PMT表)、节目流构成关系以及编解码参数获取机制。视频流参数如pix_fmt、分辨率等通过解码过程从codec_context中获取,而codec_id和类型则由PMT表中的stream_type映射确定。整个解析过程涉及SDT、PMT表解析和数据包解码分析。

hjjdebug的专栏 1169

工具Demux——简化复杂的DAPP开发

EOSIO区块链平台的主要优势之是能够开发可用、可扩展且灵活的分级应用程序。为此,Block.one很高兴地发布Demux,这是EOSIO社区的个新的开源开发工具,它可以简化复杂的DAPP开发。 Demux从Facebook的Flux架构模式和Redux中汲取灵感,创建了个后端基础架构模式,用于采集区块链事件,以确定性地更新基于EOSIO区块链的应用程序的可查询数据库。 这个建议的体...

xinshengdaxue000的博客 1168

MATLAB的Simulink常用模块(五)

MATLAB的Simulink常用模块(五)

longxingtiNXI的博客 1583

FFMPEG的应用之demux 和decoder的分离

转载时请注明出处和作者文章出处:http://www.nanbandao.com/bbs/作者:Ella     demux和decoder的分离是指将demux出来的数据通过适配层后送给硬件decode,因为HW可以直接解码。  这里记录下当初遇到的问题。       从av_read_frame出来的码流,般来讲,已经是比较正规的ES流,通过

echoheng的专栏 3504
上一篇: FFmpeg 音频重采样的两种方法libavcodec和libswresample
下一篇: FFmpeg从入门到牛掰(二):转封装(remux)讲解
im-pingo
博客等级 码龄7年 304粉丝 45原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值