36.FFmpeg学习笔记 - ffplay源码解读4之解码线程

本文详细探讨了FFmpeg中的解码线程,包括音频线程audio_thread的运作机制。在stream_component_open函数中启动了解码线程,音频线程通过循环从packet队列获取数据,解码后存入帧队列。重点分析了frame_queue_peek_writable函数,该函数在帧队列满时会等待其他线程消费帧,然后返回可写的Frame。解码函数decoder_decode_frame在获取到可写的Frame后,使用av_frame_move_ref将解码结果保存,为后续显示做准备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇说一下解码线程。

在stream_component_open函数中,分别创建了一个视频解码线程和音频解码线程:

static int stream_component_open(VideoState *is, int stream_index)
{

   ...

    switch (avctx->codec_type) {
        case AVMEDIA_TYPE_AUDIO:
            
            ...

            if ((ret = decoder_start(&is->auddec, audio_thread, is)) < 0)
                goto out;
            break;

        case AVMEDIA_TYPE_VIDEO:

            ...

            if ((ret = decoder_start(&is->viddec, video_thread, is)) < 0)
                goto out;
            break;
       
        default:
            break;
    }
    goto out;
    
fail:
    avcodec_free_context(&avctx);
    out:
    av_dict_free(&opts);
    
    return ret;
}

对函数做了一些简化,在调用decoder_start函数时,创建了音频解码线程audio_thread和视频解码线程video_thread。

由于audio_thread和video_thread的内容差不多,所以以下仅分析一下audio_thread:

static int audio_thread(void *arg)
{
    VideoState *is = arg;
    AVFrame *frame = av_frame_alloc();
    Frame *af;
    
    int got_frame = 0;
    AVRational tb;
    int ret = 0;
    
    if (!frame)
        return AVERROR(ENOMEM);
    
    do {
        if ((got_frame = decoder_decode_frame(&is->auddec, frame, NULL)) < 0)
            goto the_end;
        
        if (got_frame) {
            tb = (AVRational){1, frame->sample_rate};
            
            if (!(af = frame_queue_peek_writable(&is->sampq)))
                goto the_end;
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值