summaryrefslogtreecommitdiffstats
path: root/video/decode/dec_video.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-01-11 10:56:25 +0100
committerwm4 <wm4@nowhere>2017-01-11 11:02:57 +0100
commit77320ad45e3f1e6b08ecff4a3c0045a4864816a8 (patch)
tree9bcac59417990f8f496d3001cb7d479fb3c415d8 /video/decode/dec_video.c
parent902424d065bab52185fc2d0b177ce75012e71819 (diff)
downloadmpv-77320ad45e3f1e6b08ecff4a3c0045a4864816a8.tar.bz2
mpv-77320ad45e3f1e6b08ecff4a3c0045a4864816a8.tar.xz
video: make decoder EOF reporting explicit
This is simpler and more robust, especially for the hwdec fallback case. The most annoying issue is that C doesn't support multiple return values (or sum types), so the decode call gets all awkward. The hwdec fallback case does not need to try to produce some output after the fallback anymore. Instead, it can use the normal "replay" code path. We invert the "eof" bool that vd_lavc.c used internally. The receive_frame decoder API returns the inverse of EOF, because returning "true" from the decode function if EOF was reached feels awkward.
Diffstat (limited to 'video/decode/dec_video.c')
-rw-r--r--video/decode/dec_video.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c
index 79b706d1fd..273b80c3c9 100644
--- a/video/decode/dec_video.c
+++ b/video/decode/dec_video.c
@@ -272,19 +272,22 @@ static bool send_packet(struct dec_video *d_video, struct demux_packet *packet)
return res;
}
-static struct mp_image *receive_frame(struct dec_video *d_video)
+static bool receive_frame(struct dec_video *d_video, struct mp_image **out_image)
{
struct MPOpts *opts = d_video->opts;
+ struct mp_image *mpi = NULL;
+
+ assert(!*out_image);
MP_STATS(d_video, "start decode video");
- struct mp_image *mpi = d_video->vd_driver->receive_frame(d_video);
+ bool progress = d_video->vd_driver->receive_frame(d_video, &mpi);
MP_STATS(d_video, "end decode video");
- // Error, discarded frame, dropped frame, or initial codec delay.
+ // Error, EOF, discarded frame, dropped frame, or initial codec delay.
if (!mpi)
- return NULL;
+ return progress;
if (opts->field_dominance == 0) {
mpi->fields |= MP_IMGFIELD_TOP_FIRST | MP_IMGFIELD_INTERLACED;
@@ -356,7 +359,8 @@ static struct mp_image *receive_frame(struct dec_video *d_video)
mpi->pts -= MPMAX(delay, 0) / d_video->fps;
}
- return mpi;
+ *out_image = mpi;
+ return true;
}
void video_reset_params(struct dec_video *d_video)
@@ -403,9 +407,6 @@ void video_work(struct dec_video *d_video)
d_video->packet = NULL;
}
- bool had_input_packet = !!d_video->packet;
- bool had_packet = had_input_packet || d_video->new_segment;
-
double start_pts = d_video->start_pts;
if (d_video->start != MP_NOPTS_VALUE && (start_pts == MP_NOPTS_VALUE ||
d_video->start > start_pts))
@@ -426,19 +427,18 @@ void video_work(struct dec_video *d_video)
d_video->packet = NULL;
}
- d_video->current_mpi = receive_frame(d_video);
+ bool progress = receive_frame(d_video, &d_video->current_mpi);
d_video->current_state = DATA_OK;
- if (!d_video->current_mpi) {
+ if (!progress) {
d_video->current_state = DATA_EOF;
- if (had_packet) {
- if (framedrop_type == 1)
- d_video->dropped_frames += 1;
- d_video->current_state = DATA_AGAIN;
- }
+ } else if (!d_video->current_mpi) {
+ if (framedrop_type == 1)
+ d_video->dropped_frames += 1;
+ d_video->current_state = DATA_AGAIN;
}
- bool segment_ended = !d_video->current_mpi && !had_input_packet;
+ bool segment_ended = d_video->current_state == DATA_EOF;
if (d_video->current_mpi && d_video->current_mpi->pts != MP_NOPTS_VALUE) {
double vpts = d_video->current_mpi->pts;