代码走读: FFMPEG-ffplayer02

AVFrame

复制代码
int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)

选取一个音频解码器 和 一个视频解码器分别介绍该解码器功能

音频G722

g722dec.c -> g722_decode_frame

通过 ff_get_buffer 给 传入的 frame 指针分配内存

g722_decode_frame 函数 对应 avcodec_receive_frame

复制代码
static int g722_decode_frame(AVCodecContext *avctx, void *data,
                             int *got_frame_ptr, AVPacket *avpkt)
{
    G722Context *c = avctx->priv_data;
    AVFrame *frame = data;
    int16_t *out_buf;
    int j, ret;
    const int skip = 8 - c->bits_per_codeword;
    const int16_t *quantizer_table = low_inv_quants[skip];
    GetBitContext gb;

    /* get output buffer */
    frame->nb_samples = avpkt->size * 2;
    
    // 给frame 指针中的数据缓存指针,分配内存
    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
        return ret;
    out_buf = (int16_t *)frame->data[0];

    init_get_bits(&gb, avpkt->data, avpkt->size * 8);

    .........

}

ff_get_buffer 函数

复制代码
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
{
    int ret = get_buffer_internal(avctx, frame, flags);
    if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
        frame->width = frame->height = 0;
    }
    return ret;
}

get_buffer_internal

复制代码
====>1
static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
{

    .....
     ret = ff_attach_decode_data(frame);
    .....
}

===>2
int ff_attach_decode_data(AVFrame *frame)
{
    。。。。

    fdd_buf = av_buffer_create((uint8_t*)fdd, sizeof(*fdd), decode_data_free,
                               NULL, AV_BUFFER_FLAG_READONLY);
    .....

    return 0;
}


===>3

AVBufferRef *av_buffer_create(uint8_t *data, int size,
                              void (*free)(void *opaque, uint8_t *data),
                              void *opaque, int flags)
{
    AVBufferRef *ref = NULL;
    AVBuffer    *buf = NULL;

    buf = av_mallocz(sizeof(*buf));
    if (!buf)
        return NULL;

    buf->data     = data;
    buf->size     = size;
    buf->free     = free ? free : av_buffer_default_free;
    buf->opaque   = opaque;

    atomic_init(&buf->refcount, 1);

    if (flags & AV_BUFFER_FLAG_READONLY)
        buf->flags |= BUFFER_FLAG_READONLY;

    ref = av_mallocz(sizeof(*ref));
    if (!ref) {
        av_freep(&buf);
        return NULL;
    }

    ref->buffer = buf;
    ref->data   = data;
    ref->size   = size;

    return ref;
}

视频hevcdecSstar,星辰硬件H265解码

ss**_hevc_receive_frame 对应 avcodec_receive_frame**

复制代码
===》1

static int ss_hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{

        got_frame = 0;
        if (MI_SUCCESS == (ret2 = ss_hevc_get_frame(s, frame))) {
            got_frame = 1;
            frame->best_effort_timestamp = frame->pts;
        }

}

====>2 
static int ss_hevc_get_frame(SsHevcContext *ssctx, AVFrame *frame)
{

    ret = av_frame_get_buffer(frame, 32);


        if (MI_SUCCESS == (ret = MI_SYS_ChnOutputPortGetBuf(&stVdecChnPort, &frame_buf->stVdecBufInfo, &frame_buf->stVdecHandle)))
        {
            if (frame_buf->stVdecBufInfo.eBufType == E_MI_SYS_BUFDATA_FRAME) {
                frame_buf->bType    = FALSE;
                frame->width        = frame_buf->stVdecBufInfo.stFrameData.u16Width;
                frame->height       = frame_buf->stVdecBufInfo.stFrameData.u16Height;
            } else if (frame_buf->stVdecBufInfo.eBufType == E_MI_SYS_BUFDATA_META) {
                pstVdecInfo         = (mi_vdec_DispFrame_t *)frame_buf->stVdecBufInfo.stMetaData.pVirAddr;
                frame_buf->bType    = TRUE;
                frame_buf->s32Index = pstVdecInfo->s32Idx;
                frame->width        = pstVdecInfo->stFrmInfo.u16Width;
                frame->height       = pstVdecInfo->stFrmInfo.u16Height;
            }
            frame->opaque = (SS_Vdec_BufInfo *)frame_buf;
            frame->pts    = frame_buf->stVdecBufInfo.u64Pts;
            frame->format = ssctx->format;
        }
}

frame 释放函数

av_frame_unref

复制代码
void av_frame_unref(AVFrame *frame)
{
    int i;

    if (!frame)
        return;

    wipe_side_data(frame);

    for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
        av_buffer_unref(&frame->buf[i]);
    for (i = 0; i < frame->nb_extended_buf; i++)
        av_buffer_unref(&frame->extended_buf[i]);
    av_freep(&frame->extended_buf);
    av_dict_free(&frame->metadata);
#if FF_API_FRAME_QP
FF_DISABLE_DEPRECATION_WARNINGS
    av_buffer_unref(&frame->qp_table_buf);
FF_ENABLE_DEPRECATION_WARNINGS
#endif

    av_buffer_unref(&frame->hw_frames_ctx);

    av_buffer_unref(&frame->opaque_ref);
    av_buffer_unref(&frame->private_ref);

    get_frame_defaults(frame);
}
相关推荐
mortimer3 小时前
一键实现人声伴奏分离:基于 `uv`, `FFmpeg` 和 `audio-separator` 的高效解决方案
python·ffmpeg·音视频开发
筏.k2 天前
WebRTC 项目中捕获 FFmpeg 底层源码日志(av_log)的完整方案
ffmpeg·webrtc
学习_学习_再学习2 天前
ffmpeg学习记录
学习·ffmpeg
我科绝伦(Huanhuan Zhou)2 天前
Oracle AWR管理与快照操作完整指南
数据库·oracle·ffmpeg
梵尔纳多2 天前
ffmpeg 使用滤镜实现播放倍速
c++·qt·ffmpeg
无敌最俊朗@4 天前
音视频播放的核心处理流程
ffmpeg
mortimer5 天前
搞懂FFmpeg中2个桀骜不驯的参数:CRF 与 Preset
ffmpeg·音视频开发·视频编码
2401_841495646 天前
Windows 系统中ffmpeg安装问题的彻底解决
windows·python·ffmpeg·bug·语音识别·下载·安装步骤
八月的雨季 最後的冰吻6 天前
FFmpeg --15-视频解码: AVIO内存输入模式分析
ffmpeg·音视频
aqi006 天前
FFmpeg开发笔记(八十八)基于Compose的国产电视直播开源框架MyTV
android·ffmpeg·音视频·直播·流媒体