数据流:
1. 文件 --> ByteIOContext中的buffer --> 形成AVPacket放进PacketQueue
2. 从视频PacketQueue中获取AVPacket --> 视频解码线程 --> AVFrame --> 颜色空间转换 --> SDL_OverLay
3. 从音频PacketQueue中获取AVPacket --> 音频解码回调 --> audio_buf --> SDL音频缓存
1. 作为数据的生产者, 2 & 3 均为数据消费者;
注意: 其中PacketQueue中有许多个AVPacket, 只有一个AVFrame, SDL音频缓存可以存储一定量的音频数据
//1. 文件 --> ByteIOContext中的buffer --> 形成AVPacket放进PacketQueue. //static int decode_thread(void *arg) 代码片段, 功能主要是从底层不断的读 //取AVPacket, 并将其分发进音视频不同的PacketQueue. for(;;) { if (is->abort_request) break; ... ret = av_read_frame(ic, pkt); if (ret < 0) { if (url_ferror(&ic->pb) == 0) { SDL_Delay(100); /* wait for user event */ continue; } else break; } if (pkt->stream_index == is->audio_stream) { packet_queue_put(&is->audioq, pkt); } else if (pkt->stream_index == is->video_stream) { packet_queue_put(&is->videoq, pkt); } else if (pkt->stream_index == is->subtitle_stream) { packet_queue_put(&is->subtitleq, pkt); } else { av_free_packet(pkt); } } //2. 从视频PacketQueue中获取AVPacket --> 视频解码线程 --> AVFrame // --> 颜色空间转换 --> SDL_OverLay // 视频解码线程片段 static int video_thread(void *arg) { ... for(;;) { while (is->paused && !is->videoq.abort_request) { SDL_Delay(10); } if (packet_queue_get(&is->videoq, pkt, 1) < 0) break; /* NOTE: ipts is the PTS of the _first_ picture beginning in this packet, if any */ pts = 0; if (pkt->dts != AV_NOPTS_VALUE) pts = av_q2d(is->video_st->time_base)*pkt->dts; SDL_LockMutex(is->video_decoder_mutex); len1 = avcodec_decode_video(is->video_st->codec, frame, &got_picture, pkt->data, pkt->size); SDL_UnlockMutex(is->video_decoder_mutex); // if (len1 < 0) // break; if (got_picture) { if (output_picture2(is, frame, pts) < 0) goto the_end; } av_free_packet(pkt); if (step) if (cur_stream) stream_pause(cur_stream); } ... } //3. 从音频PacketQueue中获取AVPacket --> 音频解码回调 --> audio_buf --> SDL音频缓存 void sdl_audio_callback(void *opaque, Uint8 *stream, int len) { ... while (len > 0) { if (is->audio_buf_index >= is->audio_buf_size) { audio_size = audio_decode_frame(is, is->audio_buf, &pts); if (audio_size < 0) { /* if error, just output silence */ is->audio_buf_size = 1024; memset(is->audio_buf, 0, is->audio_buf_size); } else { if (is->show_audio) update_sample_display(is, (int16_t *)is->audio_buf, audio_size); audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size, pts); is->audio_buf_size = audio_size; } is->audio_buf_index = 0; } len1 = is->audio_buf_size - is->audio_buf_index; if (len1 > len) len1 = len; memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1); len -= len1; stream += len1; is->audio_buf_index += len1; } }