这一部分,说起来会比较简单,但是做起来会比较长。
首先,要说多线程,C里面推荐使用pthread,直接使用pthread_create就能创建一个线程。关于pthread的使用,其他时间有空再说吧。这里主要是要传入一个指针函数,用于定义线程中的逻辑。
然后,要创建几个数据队列,用于存放画面和音频的数据。队列这个数据结构应该网上一搜一大把,就不重复说明了
Player *player = (Player *) arg;
AVPacket *packet = av_packet_alloc();
for (;;) {
pthread_mutex_lock(&seek_mutex);
while (is_seek) {
LOGE("Player Log : produce waiting seek");
pthread_cond_wait(&seek_condition, &seek_mutex);
LOGE("Player Log : produce wake up seek");
}
pthread_mutex_unlock(&seek_mutex);
if (av_read_frame(player->format_context, packet) < 0) {
break;
}
if (packet->stream_index == player->video_stream_index) {
queue_in(player->video_queue, packet);
} else if (packet->stream_index == player->audio_stream_index) {
queue_in(player->audio_queue, packet);
}
packet = av_packet_alloc();
}
break_block(player->video_queue);
break_block(player->audio_queue);
for (;;) {
if (queue_is_empty(player->video_queue) && queue_is_empty(player->audio_queue)) {
break;
}
sleep(1);
}
player_release(player);
return NULL;
这里控制了队列大小,如果超限输入就会阻塞,等待消费掉再继续读入。
最后,就是要用一个线程来读数据,分别存到上面创建的队列里面,再用对应数量的线程来解码和输出画面和音频等。
pthread_create(&produce_id, NULL, produce, player);
Consumer *video_consumer = (Consumer *) malloc(sizeof(Consumer));
video_consumer->player = player;
video_consumer->stream_index = player->video_stream_index;
pthread_create(&video_consume_id, NULL, consume, video_consumer);
Consumer *audio_consumer = (Consumer *) malloc(sizeof(Consumer));
audio_consumer->player = player;
audio_consumer->stream_index = player->audio_stream_index;
pthread_create(&audio_consume_id, NULL, consume, audio_consumer);
produce是个指针函数,指向读取方法
Consumer里面集成前两节说的输出画面和音频,这样画面和音频就同时输出完成了。当然,差异是会有的,比如读入:
pthread_mutex_lock(&seek_mutex);
while (is_seek) {
pthread_cond_wait(&seek_condition, &seek_mutex);
}
pthread_mutex_unlock(&seek_mutex);
AVPacket *packet = queue_out(queue);
if (packet == NULL) {
LOGE("consume packet is null");
break;
}
不再是从流里面直接读入,而是通过缓存队列取数据,但是其他的操作是一样的。
这样视频播放就说完了。
再编码和filter这些,后续研究了再继续。
待续...不定期更新了