陆小曼超详细解析FFplay之音视频解码线程( 四 )


获取?个packet , 如果播放序列不?致(数据不连续)则过滤掉“过时”的packet , 怎么理解呢?
// 2 获取?个packet , 如果播放序列不?致(数据不连续)则过滤掉“过时”的packetdo {// 2.1 如果没有数据可读则唤醒read_thread, 实际是continue_read_thread S DL_condif (d->queue->nb_packets == 0) // 没有数据可读SDL_CondSignal(d->empty_queue_cond);// 通知read_thread放?packet// 2.2 如果还有pending的packet则使?它if (d->packet_pending) {av_packet_move_ref(&pkt, &d->pkt);d->packet_pending = 0;} else {// 2.3 阻塞式读取packet , 这?好理解 , 就是读packet并获取serialif (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)return -1;}if(d->queue->serial != d->pkt_serial) {// darren??的代码printf("%s(%d) discontinue:queue->serial:%d,pkt_serial:%d\n" ,__FUNCTION__, __LINE__, d->queue->serial, d->pkt_seri al);av_packet_unref(&pkt); // fixed me? 释放要过滤的packet}} while (d->queue->serial != d->pkt_serial);// 如果不是同?播放序列(流不连续)则继续读取(1)如果还有pending的packet则使?它 , pending就表示Packet还没发送完 。
// 2.2 如果还有pending的packet则使?它if (d->packet_pending) {av_packet_move_ref(&pkt, &d->pkt);d->packet_pending = 0;}
pending包packet和 packet_pending 的概念的来源 , 来?send失败时重新发送:
if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) {av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet bot h returned EAGAIN, which is an API violation.\n");d->packet_pending = 1;av_packet_move_ref(&d->pkt, &pkt);}如果 avcodec_send_packet 返回 EAGAIN, 则把当前 pkt 存? d->pkt, 然后置标志位packet_pending 为1 。
(2)do {} while (d->queue->serial != d->pkt_serial);这个意思就是说 , 如果不是同?播放序列(流不连续)则继续读取 。
d->queue->serial是最新的播放序列 , 当读取出来的packet的serial和最新的serial不同时则过滤掉 , 继续读取packet , 但检测到不是同?serial , 是不是应该释放掉packet的数据??如下列代码:
if(d->queue->serial != d->pkt_serial) {printf("%s(%d) discontinue:queue->serial:%d,pkt_serial:%d\n",__FUNCTION__, __LINE__, d->queue->serial, d->pkt_serial);av_packet_unref(&pkt); // fixed me? 释放要过滤的packet}将packet送?解码器
// 3 将packet送?解码器if (pkt.data =http://news.hoteastday.com/a/= flush_pkt.data) {//// when seeking or when switching to a different streamavcodec_flush_buffers(d->avctx); //清空??的缓存帧d->finished = 0; // 重置为0d->next_pts = d->start_pts; // 主要?在了audiod->next_pts_tb = d->start_pts_tb;// 主要?在了audio} else {if (d->avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {int got_frame = 0;ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &p kt);if (ret < 0) {ret = AVERROR(EAGAIN);} else {if (got_frame && !pkt.data) {d->packet_pending = 1;av_packet_move_ref(&d->pkt, &pkt);}ret = got_frame ? 0 : (pkt.data ? AVERROR(EAGAIN) : AVER ROR_EOF);}} else {//将packet送?解码器if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) {av_log(d->avctx, AV_LOG_ERROR,"Receive_frame and send_p acket both returned EAGAIN, which is an API violation.\n");d->packet_pending = 1;25 av_packet_move_ref(&d->pkt, &pkt);}}av_packet_unref(&pkt); // ?定要??去释放?视频 字幕数据}


推荐阅读