Call avcodec_receive_frame() in a loop

Since in scrcpy a video packet passed to avcodec_send_packet() is always
a complete video frame, it is sufficient to call avcodec_receive_frame()
exactly once.

In practice, it also works for audio packets: the decoder produces
exactly 1 frame for 1 input packet.

In theory, it is an implementation detail though, so
avcodec_receive_frame() should be called in a loop.
This commit is contained in:
Romain Vimont 2023-02-28 21:20:28 +01:00
parent c1528cdca9
commit 6e05d7047a

View file

@ -110,8 +110,19 @@ sc_decoder_push(struct sc_decoder *decoder, const AVPacket *packet) {
decoder->name, ret); decoder->name, ret);
return false; return false;
} }
ret = avcodec_receive_frame(decoder->codec_ctx, decoder->frame);
if (!ret) { for (;;) {
ret = avcodec_receive_frame(decoder->codec_ctx, decoder->frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
}
if (ret) {
LOGE("Decoder '%s', could not receive video frame: %d",
decoder->name, ret);
return false;
}
// a frame was received // a frame was received
bool ok = push_frame_to_sinks(decoder, decoder->frame); bool ok = push_frame_to_sinks(decoder, decoder->frame);
// A frame lost should not make the whole pipeline fail. The error, if // A frame lost should not make the whole pipeline fail. The error, if
@ -119,11 +130,8 @@ sc_decoder_push(struct sc_decoder *decoder, const AVPacket *packet) {
(void) ok; (void) ok;
av_frame_unref(decoder->frame); av_frame_unref(decoder->frame);
} else if (ret != AVERROR(EAGAIN)) {
LOGE("Decoder '%s', could not receive video frame: %d",
decoder->name, ret);
return false;
} }
return true; return true;
} }