• 代码走读: 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

    1. static int g722_decode_frame(AVCodecContext *avctx, void *data,
    2. int *got_frame_ptr, AVPacket *avpkt)
    3. {
    4. G722Context *c = avctx->priv_data;
    5. AVFrame *frame = data;
    6. int16_t *out_buf;
    7. int j, ret;
    8. const int skip = 8 - c->bits_per_codeword;
    9. const int16_t *quantizer_table = low_inv_quants[skip];
    10. GetBitContext gb;
    11. /* get output buffer */
    12. frame->nb_samples = avpkt->size * 2;
    13. // 给frame 指针中的数据缓存指针,分配内存
    14. if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
    15. return ret;
    16. out_buf = (int16_t *)frame->data[0];
    17. init_get_bits(&gb, avpkt->data, avpkt->size * 8);
    18. .........
    19. }

    ff_get_buffer 函数

    1. int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
    2. {
    3. int ret = get_buffer_internal(avctx, frame, flags);
    4. if (ret < 0) {
    5. av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
    6. frame->width = frame->height = 0;
    7. }
    8. return ret;
    9. }

    get_buffer_internal 

    1. ====>1
    2. static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
    3. {
    4. .....
    5. ret = ff_attach_decode_data(frame);
    6. .....
    7. }
    8. ===>2
    9. int ff_attach_decode_data(AVFrame *frame)
    10. {
    11. 。。。。
    12. fdd_buf = av_buffer_create((uint8_t*)fdd, sizeof(*fdd), decode_data_free,
    13. NULL, AV_BUFFER_FLAG_READONLY);
    14. .....
    15. return 0;
    16. }
    17. ===>3
    18. AVBufferRef *av_buffer_create(uint8_t *data, int size,
    19. void (*free)(void *opaque, uint8_t *data),
    20. void *opaque, int flags)
    21. {
    22. AVBufferRef *ref = NULL;
    23. AVBuffer *buf = NULL;
    24. buf = av_mallocz(sizeof(*buf));
    25. if (!buf)
    26. return NULL;
    27. buf->data = data;
    28. buf->size = size;
    29. buf->free = free ? free : av_buffer_default_free;
    30. buf->opaque = opaque;
    31. atomic_init(&buf->refcount, 1);
    32. if (flags & AV_BUFFER_FLAG_READONLY)
    33. buf->flags |= BUFFER_FLAG_READONLY;
    34. ref = av_mallocz(sizeof(*ref));
    35. if (!ref) {
    36. av_freep(&buf);
    37. return NULL;
    38. }
    39. ref->buffer = buf;
    40. ref->data = data;
    41. ref->size = size;
    42. return ref;
    43. }

    视频hevcdecSstar,星辰硬件H265解码

    ss_hevc_receive_frame 对应 avcodec_receive_frame

    1. ===1
    2. static int ss_hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
    3. {
    4. got_frame = 0;
    5. if (MI_SUCCESS == (ret2 = ss_hevc_get_frame(s, frame))) {
    6. got_frame = 1;
    7. frame->best_effort_timestamp = frame->pts;
    8. }
    9. }
    10. ====>2
    11. static int ss_hevc_get_frame(SsHevcContext *ssctx, AVFrame *frame)
    12. {
    13. ret = av_frame_get_buffer(frame, 32);
    14. if (MI_SUCCESS == (ret = MI_SYS_ChnOutputPortGetBuf(&stVdecChnPort, &frame_buf->stVdecBufInfo, &frame_buf->stVdecHandle)))
    15. {
    16. if (frame_buf->stVdecBufInfo.eBufType == E_MI_SYS_BUFDATA_FRAME) {
    17. frame_buf->bType = FALSE;
    18. frame->width = frame_buf->stVdecBufInfo.stFrameData.u16Width;
    19. frame->height = frame_buf->stVdecBufInfo.stFrameData.u16Height;
    20. } else if (frame_buf->stVdecBufInfo.eBufType == E_MI_SYS_BUFDATA_META) {
    21. pstVdecInfo = (mi_vdec_DispFrame_t *)frame_buf->stVdecBufInfo.stMetaData.pVirAddr;
    22. frame_buf->bType = TRUE;
    23. frame_buf->s32Index = pstVdecInfo->s32Idx;
    24. frame->width = pstVdecInfo->stFrmInfo.u16Width;
    25. frame->height = pstVdecInfo->stFrmInfo.u16Height;
    26. }
    27. frame->opaque = (SS_Vdec_BufInfo *)frame_buf;
    28. frame->pts = frame_buf->stVdecBufInfo.u64Pts;
    29. frame->format = ssctx->format;
    30. }
    31. }

    frame 释放函数

    av_frame_unref

    1. void av_frame_unref(AVFrame *frame)
    2. {
    3. int i;
    4. if (!frame)
    5. return;
    6. wipe_side_data(frame);
    7. for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
    8. av_buffer_unref(&frame->buf[i]);
    9. for (i = 0; i < frame->nb_extended_buf; i++)
    10. av_buffer_unref(&frame->extended_buf[i]);
    11. av_freep(&frame->extended_buf);
    12. av_dict_free(&frame->metadata);
    13. #if FF_API_FRAME_QP
    14. FF_DISABLE_DEPRECATION_WARNINGS
    15. av_buffer_unref(&frame->qp_table_buf);
    16. FF_ENABLE_DEPRECATION_WARNINGS
    17. #endif
    18. av_buffer_unref(&frame->hw_frames_ctx);
    19. av_buffer_unref(&frame->opaque_ref);
    20. av_buffer_unref(&frame->private_ref);
    21. get_frame_defaults(frame);
    22. }

  • 相关阅读:
    二分查找(搜索区间为左闭右开)
    Java数组与八大排序
    Java单表实现评论回复功能
    linux操作系统
    elf文件与链接脚本
    Android 基础知识3-1项目目录结构
    BUG记录-窗体初始化时无法正确获取控件大小
    机器学习基础知识(3)
    Nginx (7):nginx高可用配置
    LeetCode笔记:Biweekly Contest 81
  • 原文地址:https://blog.csdn.net/kekeleqy/article/details/132841108