代码走读: 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);
}
相关推荐
小狮子安度因5 小时前
ffplay数据结构分析
数据结构·ffmpeg
小狮子安度因11 小时前
ffplay音频重采样
ffmpeg·音视频
小狮子安度因20 小时前
AAC ADTS格式分析
网络·ffmpeg·aac
勘察加熊人1 天前
ffmpeg切割音频
ffmpeg·音视频
xiaohouzi1122332 天前
Python读取视频-硬解和软解
python·opencv·ffmpeg·视频编解码·gstreamer
kimble_xia@oracle3 天前
性能优化笔记
ffmpeg
wang_chao1183 天前
RK3399平台ffmpeg-VPU硬编码录制USB摄像头视频、H264或MJPEG编码
ffmpeg·音视频
鹅毛在路上了4 天前
C++, ffmpeg, libavcodec-RTSP拉流,opencv实时预览
c++·opencv·ffmpeg
Hi202402176 天前
Orin-Apollo园区版本:订阅多个摄像头画面拼接与硬编码RTMP推流
ffmpeg·apollo·orin·图像拼接·图传
蓝纹绿茶6 天前
Python程序使用了Ffmpeg,结束程序后,文件夹中仍然生成音频、视频文件
python·ubuntu·ffmpeg·音视频