Ffmpeg 如何理解给定的ffplay C代码片段?
以下代码段来自: 有人能帮我吗 谢谢。请参阅提交 现在串行通信有两个目的:提交的最初目的是能够区分数据包队列中的数据包与查找前后的数据包。解复用器(数据包队列的输入)在单独的线程中运行。在搜索之后,我们希望刷新它,但我们不想停止生产者线程,因为这会增加开销。然而,我们也不希望刷新太少或太多的数据包。因此,串行字段告诉我们哪些数据包是预刷新和后刷新的,因此在丢弃这些数据包时不必停止生产者线程就可以丢弃哪些数据包 第二个用途是代码行:它告诉我们何时发生EOF。Finished设置为用于解码帧的数据包队列中数据包的最后一个序列号。如果该序列号也是数据包队列的尾部(并且不再生成数据包),则意味着我们停止生成数据包并解码属于该数据包的帧。换句话说:文件结束。在其他地方,您将沿着这些行找到一个测试,然后要么停止播放,要么(如果启用了循环),我们返回到文件的开头(即调用循环行为)Ffmpeg 如何理解给定的ffplay C代码片段?,ffmpeg,Ffmpeg,以下代码段来自: 有人能帮我吗 谢谢。请参阅提交 现在串行通信有两个目的:提交的最初目的是能够区分数据包队列中的数据包与查找前后的数据包。解复用器(数据包队列的输入)在单独的线程中运行。在搜索之后,我们希望刷新它,但我们不想停止生产者线程,因为这会增加开销。然而,我们也不希望刷新太少或太多的数据包。因此,串行字段告诉我们哪些数据包是预刷新和后刷新的,因此在丢弃这些数据包时不必停止生产者线程就可以丢弃哪些数据包 第二个用途是代码行:它告诉我们何时发生EOF。Finished设置为用于解码帧的数据包
(这篇文章得到了IRC上几个FFmpeg开发人员的帮助。)我发现了一个问题,
d->finished=d->pkt_serial;//连接音频流时已执行标志
。这显然不是EOF。此外,我还启用了设置:fflags-nobuffer
。所以我很困惑,Finished是不断更新的,我想你的意思是缓冲区是空的,但还没有完成。这可能真的是一个bug,值得向上游发布bug报告:是的,这就是我的意思。谢谢
static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
int got_frame = 0;
do {
int ret = -1;
if (d->queue->abort_request)
return -1;
if (!d->packet_pending || d->queue->serial != d->pkt_serial) {
AVPacket pkt;
do {
if (d->queue->nb_packets == 0)
SDL_CondSignal(d->empty_queue_cond);
if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)
return -1;
if (pkt.data == flush_pkt.data) {
avcodec_flush_buffers(d->avctx);
d->finished = 0;
d->next_pts = d->start_pts;
d->next_pts_tb = d->start_pts_tb;
}
} while (pkt.data == flush_pkt.data || d->queue->serial != d->pkt_serial);
av_free_packet(&d->pkt);
d->pkt_temp = d->pkt = pkt;
d->packet_pending = 1;
}
switch (d->avctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
ret = avcodec_decode_video2(d->avctx, frame, &got_frame, &d->pkt_temp);
if (got_frame) {
if (decoder_reorder_pts == -1) {
frame->pts = av_frame_get_best_effort_timestamp(frame);
} else if (decoder_reorder_pts) {
frame->pts = frame->pkt_pts;
} else {
frame->pts = frame->pkt_dts;
}
}
break;
case AVMEDIA_TYPE_AUDIO:
ret = avcodec_decode_audio4(d->avctx, frame, &got_frame, &d->pkt_temp);
if (got_frame) {
AVRational tb = (AVRational){1, frame->sample_rate};
if (frame->pts != AV_NOPTS_VALUE)
frame->pts = av_rescale_q(frame->pts, d->avctx->time_base, tb);
else if (frame->pkt_pts != AV_NOPTS_VALUE)
frame->pts = av_rescale_q(frame->pkt_pts, av_codec_get_pkt_timebase(d->avctx), tb);
else if (d->next_pts != AV_NOPTS_VALUE)
frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
if (frame->pts != AV_NOPTS_VALUE) {
d->next_pts = frame->pts + frame->nb_samples;
d->next_pts_tb = tb;
}
}
break;
case AVMEDIA_TYPE_SUBTITLE:
ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &d->pkt_temp);
break;
}
if (ret < 0) {
d->packet_pending = 0;
} else {
d->pkt_temp.dts =
d->pkt_temp.pts = AV_NOPTS_VALUE;
if (d->pkt_temp.data) {
if (d->avctx->codec_type != AVMEDIA_TYPE_AUDIO)
ret = d->pkt_temp.size;
d->pkt_temp.data += ret;
d->pkt_temp.size -= ret;
if (d->pkt_temp.size <= 0)
d->packet_pending = 0;
} else {
if (!got_frame) {
d->packet_pending = 0;
d->finished = d->pkt_serial; // FLAG
}
}
}
} while (!got_frame && !d->finished);
return got_frame;
}
d->finished = d->pkt_serial; // FLAG