文档章节

把 ffmpeg AVAudioFifo/AVFrame 数据读到共享内存

UMU
 UMU
发布于 2017/07/20 16:45
字数 513
阅读 86
收藏 0

一般情况下操作 AVAudioFifo/AVFrame 都是用全套 ffmpeg API,内部自己管理内存,不需要了解它们内部怎么组织内存。比如:

inline int InitFrame(AVFrame *&frame, int frame_size = kTargetSamplesPerFrame)
{
    frame = av_frame_alloc();
    if (nullptr == frame) {
        return AVERROR(ENOMEM);
    }

    frame->nb_samples = frame_size;
    frame->channel_layout = av_get_default_channel_layout(kTargetChannels);
    frame->format = kTargetSampleFormat;
    frame->sample_rate = kTargetSampleRate;

    int error = av_frame_get_buffer(frame, 0);
    if (error < 0) {
        av_frame_free(&frame);
        ATLTRACE2(atlTraceException, 0, "!av_frame_get_buffer(), #%d, %s\n", error, GetAvErrorText(error));
    }
    return error;
}

{
    ...
    AVFrame *frame;
    error_code = InitFrame(frame);
    if (error_code < 0) {
        ATLTRACE2(atlTraceException, 0, __FUNCTION__ ": !InitFrame(), #%d\n", error_code);
        return error_code;
    }
    ON_SCOPE_EXIT([&] {
        av_frame_free(&frame);
    });
    
    int read_size = av_audio_fifo_read(fifo_, (void **)frame->data, kTargetSamplesPerFrame);
    ...
}

这里读了一个 AVFrame 出来,并不需要知道具体的内存布局,但如果要写入 FileMapping 对象里,就得知道了!参考以下函数:

int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
{
    int i, size;

    if (nb_samples < 0)
        return AVERROR(EINVAL);
    nb_samples = FFMIN(nb_samples, af->nb_samples);
    if (!nb_samples)
        return 0;

    size = nb_samples * af->sample_size;
    for (i = 0; i < af->nb_buffers; i++) {
        if (av_fifo_generic_read(af->buf[i], data[i], size, NULL) < 0)
            return AVERROR_BUG;
    }
    af->nb_samples -= nb_samples;

    return nb_samples;
}

和 AVFrame 定义:

typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
    /**
     * pointer to the picture/channel planes.
     * This might be different from the first allocated byte
     *
     * Some decoders access areas outside 0,0 - width,height, please
     * see avcodec_align_dimensions2(). Some filters and swscale can read
     * up to 16 bytes beyond the planes, if these filters are to be used,
     * then 16 extra bytes must be allocated.
     *
     * NOTE: Except for hwaccel formats, pointers not needed by the format
     * MUST be set to NULL.
     */
    uint8_t *data[AV_NUM_DATA_POINTERS];

    /**
     * For video, size in bytes of each picture line.
     * For audio, size in bytes of each plane.
     *
     * For audio, only linesize[0] may be set. For planar audio, each channel
     * plane must be the same size.
     *
     * For video the linesizes should be multiples of the CPUs alignment
     * preference, this is 16 or 32 for modern desktop CPUs.
     * Some code requires such alignment other code can be slower without
     * correct alignment, for yet other it makes no difference.
     *
     * @note The linesize may be larger than the size of usable data -- there
     * may be extra padding present for performance reasons.
     */
    int linesize[AV_NUM_DATA_POINTERS];
...
};

以 AV_SAMPLE_FMT_S16 为例,发现 InitFrame() 里的 av_frame_get_buffer() 之后只有 linesize[0] 是非 0,即 data[0] 的分配长度,其它 7 个都是 0,即 data[1] -> data[7] 都没有分配,于是猜测就是读 data[0],长度 linesize[0],尝试把它写到 FileMapping 里,果然是对的。如果 SampleFormat 是带 P 的,就不是只有 data[0] 了,有几个 channel 就有几个 data,要相应改变。

© 著作权归作者所有

共有 人打赏支持
UMU

UMU

粉丝 119
博文 112
码字总数 44043
作品 0
厦门
程序员
私信 提问
学习FFmpeg API – 解码视频

ffmpeg是编解码的利器,用了很久,以前看过dranger 的教程,非常精彩,受益颇多,是学习ffmpeg api很好的材料。可惜的是其针对的ffmpeg版本已经比较老了,而ffmpeg的更新又很快,有些API已经...

霄霄月月
2012/05/08
0
32
FFmpeg命令行工具学习(四):FFmpeg API 介绍与通用 API 分析

一、FFmpeg 相关术语 1. 容器/文件(Container/File):即特定格式的多媒体文件,比如MP4,flv,mov等。 2. 媒体流(Stream):表示在时间轴上的一段连续的数据,比如一段声音数据、一段视频...

灰色飘零
07/17
0
0
ffmpeg从AVFrame取出yuv数据到保存到char*中

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhuweigangzwg/article/details/43734169 ffmpeg从AVFrame取出yuv数据到保存到char*中 交流请加QQ群:6205482...

zwg流泪
2015/02/11
0
0
使用 liavformat 和 libavcodec 实现解码器

使用ffmpeg 的liavformat 解封装,使用libavcodec 解codec,实现一个简单的解码器。 解码的流程,从数据结构上看就是AVFormatContext ->AVCodecContext -> AVPacket -> AVFrame。 生成AVPac...

鼎铭
07/09
0
0
FFmpeg编写一个简单播放器 -1

指导1:制作屏幕录像 概要 电影文件有很多基本的组成部分。首先,文件本身被称为容器Container,容器的类型决定了信息被存放在文件中的位置。AVI和Quicktime就是容器的例子。接着,你有一组流...

GuoKai
2012/09/19
0
1

没有更多内容

加载失败,请刷新页面

加载更多

生物智能与AI——关乎创造、关乎理解(上)

摘要: 原来人工智能跟人类智能有那么深的联系! 几百万年前,第一次人类智能的星火出现在非洲大陆,并且持续发展,最终在大约10万年前在智人的大脑中达到顶峰。作为现代人类,我们只能想象我...

阿里云官方博客
16分钟前
2
0
MiniUi系列 详情逻辑

row是获取的行的数据,通过id去查看对应id的详情,所有数据是在datagrid加载完后的,比如有5条,我可以选中某一条,我也可以把获取到的数据直接传到详情页面,仅就是追加row.xx,row.xx,这样就...

architect刘源源
17分钟前
3
0
android adb实用命令小结

adb的全称为Android Debug Bridge.是android司机经常用到的工具.但是问题是那么多命令写代码已经够费劲了,过段时间在次使用时压根记不住呀.本次的大餐就是为此开篇的.这一次我们不记命令.要用...

天王盖地虎626
21分钟前
2
0
vagrant 虚拟机 磁盘100%解决

在日常开发中,我使用vagrant+VirtualBox搭建开发环境 docker+docker-compose搭建了php+nginx+redis+mysql+ELK(Elasticsearch+Kibana+Logstash+php)+phpredisadmin 但是搭建了环境之后发现磁...

DamienChen
26分钟前
2
0
详解如何用爬虫批量抓取百度搜索多个关键字数据

本文介绍如何使用软件的流程图模式,免费采集百度搜索多个关键字的信息数据。 软件下载网址:www.houyicaiji.com 采集结果预览: 下面我们来详细介绍一下如何使用流程图模式,采集在百度输入...

技术阿飞
28分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部