ffmpeg 播放流程及线程管理

本文以ffmpeg中的ffplay为例,分析其音视频的播放流程,以及线程管理。

一、主线程
main()
{
    // 首先是初始化:
    avcodec_register_all()
    av_register_all()

    // 打开read线程
    stream_open(input_filename, file_iformat);
    => SDL_CreateThread(read_thread, is); // 打开read线程,

    // 主线程进入消息循环,处理用户输入
    event_loop(is); 
}

二、数据流
ffplay将由read线程读取input数据流(文件、network etc.),数据读入共同维护的packet队列:is->videoq, is->audioq
同时,音视频解码线程从队列中读取并进行解码。

三、read线程
read_thread()
{
    // 打开input,创建不同的stream
    avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
    
    // 分析不同stream信息,得到相应解码器信息
    avformat_find_stream_info(ic, opts);
    
    // 启动解码线程
    stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
    {
        audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)
        => SDL_OpenAudio(&wanted_spec, &spec) 
        // 这里传入 sdl_audio_callback,SDL回调后在sdl_audio_callback中进行音频解码。
    }
    stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
    {
        // 对于video:
        SDL_CreateThread(video_thread, is); // 启动video解码线程
    }
    
    // read线程进入读取input数据的循环
    for (;;) {
        av_read_frame(ic, pkt);
    }
}

三、音视频解码线程
sdl_audio_callback(&stream) 
{
    // 解码
    audio_decode_frame(is);
    // 引用参数返回解码后数据
    memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
    // 最后由SDL输出到硬件
}

video_thread()
{
    for (;;) {
        // 解码
        get_video_frame(is, frame, &pkt, &serial);
        // 输出
        queue_picture(is, frame, pts, pkt.pos, serial);
    }

}


你可能感兴趣的:(多媒体,多媒体,ffmpeg)