1 /* GStreamer
2 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * SECTION:gstvp8decoder
22 * @title: GstVp8Decoder
23 * @short_description: Base class to implement stateless VP8 decoders
24 * @sources:
25 * - gstvp8picture.h
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <gst/base/base.h>
33 #include "gstvp8decoder.h"
34
35 GST_DEBUG_CATEGORY (gst_vp8_decoder_debug);
36 #define GST_CAT_DEFAULT gst_vp8_decoder_debug
37
38 struct _GstVp8DecoderPrivate
39 {
40 gint width;
41 gint height;
42
43 gboolean had_sequence;
44 GstVp8Parser parser;
45 gboolean wait_keyframe;
46 guint preferred_output_delay;
47 /* for delayed output */
48 GstQueueArray *output_queue;
49 gboolean is_live;
50 };
51
52 typedef struct
53 {
54 GstVideoCodecFrame *frame;
55 GstVp8Picture *picture;
56 GstVp8Decoder *self;
57 } GstVp8DecoderOutputFrame;
58
59 #define parent_class gst_vp8_decoder_parent_class
60 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstVp8Decoder, gst_vp8_decoder,
61 GST_TYPE_VIDEO_DECODER,
62 G_ADD_PRIVATE (GstVp8Decoder);
63 GST_DEBUG_CATEGORY_INIT (gst_vp8_decoder_debug, "vp8decoder", 0,
64 "VP8 Video Decoder"));
65
66 static gboolean gst_vp8_decoder_start (GstVideoDecoder * decoder);
67 static gboolean gst_vp8_decoder_stop (GstVideoDecoder * decoder);
68 static gboolean gst_vp8_decoder_set_format (GstVideoDecoder * decoder,
69 GstVideoCodecState * state);
70 static GstFlowReturn gst_vp8_decoder_finish (GstVideoDecoder * decoder);
71 static gboolean gst_vp8_decoder_flush (GstVideoDecoder * decoder);
72 static GstFlowReturn gst_vp8_decoder_drain (GstVideoDecoder * decoder);
73 static GstFlowReturn gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder,
74 GstVideoCodecFrame * frame);
75 static void gst_vp8_decoder_clear_output_frame (GstVp8DecoderOutputFrame *
76 output_frame);
77 static void gst_vp8_decoder_drain_output_queue (GstVp8Decoder * self,
78 guint num, GstFlowReturn * ret);
79 static GstFlowReturn gst_vp8_decoder_drain_internal (GstVp8Decoder * self,
80 gboolean wait_keyframe);
81
82 static void
gst_vp8_decoder_class_init(GstVp8DecoderClass * klass)83 gst_vp8_decoder_class_init (GstVp8DecoderClass * klass)
84 {
85 GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
86
87 decoder_class->start = GST_DEBUG_FUNCPTR (gst_vp8_decoder_start);
88 decoder_class->stop = GST_DEBUG_FUNCPTR (gst_vp8_decoder_stop);
89 decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_vp8_decoder_set_format);
90 decoder_class->finish = GST_DEBUG_FUNCPTR (gst_vp8_decoder_finish);
91 decoder_class->flush = GST_DEBUG_FUNCPTR (gst_vp8_decoder_flush);
92 decoder_class->drain = GST_DEBUG_FUNCPTR (gst_vp8_decoder_drain);
93 decoder_class->handle_frame =
94 GST_DEBUG_FUNCPTR (gst_vp8_decoder_handle_frame);
95 }
96
97 static void
gst_vp8_decoder_init(GstVp8Decoder * self)98 gst_vp8_decoder_init (GstVp8Decoder * self)
99 {
100 gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
101
102 self->priv = gst_vp8_decoder_get_instance_private (self);
103 }
104
105 static gboolean
gst_vp8_decoder_start(GstVideoDecoder * decoder)106 gst_vp8_decoder_start (GstVideoDecoder * decoder)
107 {
108 GstVp8Decoder *self = GST_VP8_DECODER (decoder);
109 GstVp8DecoderPrivate *priv = self->priv;
110
111 gst_vp8_parser_init (&priv->parser);
112 priv->wait_keyframe = TRUE;
113
114 priv->output_queue =
115 gst_queue_array_new_for_struct (sizeof (GstVp8DecoderOutputFrame), 1);
116 gst_queue_array_set_clear_func (priv->output_queue,
117 (GDestroyNotify) gst_vp8_decoder_clear_output_frame);
118
119 return TRUE;
120 }
121
122 static void
gst_vp8_decoder_reset(GstVp8Decoder * self)123 gst_vp8_decoder_reset (GstVp8Decoder * self)
124 {
125 GstVp8DecoderPrivate *priv = self->priv;
126
127 gst_vp8_picture_clear (&self->last_picture);
128 gst_vp8_picture_clear (&self->golden_ref_picture);
129 gst_vp8_picture_clear (&self->alt_ref_picture);
130
131 priv->wait_keyframe = TRUE;
132 gst_queue_array_clear (priv->output_queue);
133 }
134
135 static gboolean
gst_vp8_decoder_stop(GstVideoDecoder * decoder)136 gst_vp8_decoder_stop (GstVideoDecoder * decoder)
137 {
138 GstVp8Decoder *self = GST_VP8_DECODER (decoder);
139 GstVp8DecoderPrivate *priv = self->priv;
140
141 if (self->input_state) {
142 gst_video_codec_state_unref (self->input_state);
143 self->input_state = NULL;
144 }
145
146 gst_vp8_decoder_reset (self);
147 gst_queue_array_free (priv->output_queue);
148
149 return TRUE;
150 }
151
152 static GstFlowReturn
gst_vp8_decoder_check_codec_change(GstVp8Decoder * self,const GstVp8FrameHdr * frame_hdr)153 gst_vp8_decoder_check_codec_change (GstVp8Decoder * self,
154 const GstVp8FrameHdr * frame_hdr)
155 {
156 GstVp8DecoderPrivate *priv = self->priv;
157 GstFlowReturn ret = GST_FLOW_OK;
158 gboolean changed = FALSE;
159
160 if (priv->width != frame_hdr->width || priv->height != frame_hdr->height) {
161 GST_INFO_OBJECT (self, "resolution changed %dx%d", frame_hdr->width,
162 frame_hdr->height);
163 priv->width = frame_hdr->width;
164 priv->height = frame_hdr->height;
165 changed = TRUE;
166 }
167
168 if (changed || !priv->had_sequence) {
169 GstVp8DecoderClass *klass = GST_VP8_DECODER_GET_CLASS (self);
170
171 /* Drain before new sequence */
172 ret = gst_vp8_decoder_drain_internal (self, FALSE);
173 if (ret != GST_FLOW_OK) {
174 GST_WARNING_OBJECT (self, "Failed to drain pending frames, returned %s",
175 gst_flow_get_name (ret));
176 return ret;
177 }
178
179 priv->had_sequence = TRUE;
180
181 if (klass->get_preferred_output_delay)
182 priv->preferred_output_delay =
183 klass->get_preferred_output_delay (self, priv->is_live);
184 else
185 priv->preferred_output_delay = 0;
186
187 if (klass->new_sequence)
188 ret = klass->new_sequence (self, frame_hdr);
189 }
190
191 return ret;
192 }
193
194 static gboolean
gst_vp8_decoder_set_format(GstVideoDecoder * decoder,GstVideoCodecState * state)195 gst_vp8_decoder_set_format (GstVideoDecoder * decoder,
196 GstVideoCodecState * state)
197 {
198 GstVp8Decoder *self = GST_VP8_DECODER (decoder);
199 GstVp8DecoderPrivate *priv = self->priv;
200 GstQuery *query;
201
202 GST_DEBUG_OBJECT (decoder, "Set format");
203
204 if (self->input_state)
205 gst_video_codec_state_unref (self->input_state);
206
207 self->input_state = gst_video_codec_state_ref (state);
208
209 priv->width = GST_VIDEO_INFO_WIDTH (&state->info);
210 priv->height = GST_VIDEO_INFO_HEIGHT (&state->info);
211
212 query = gst_query_new_latency ();
213 if (gst_pad_peer_query (GST_VIDEO_DECODER_SINK_PAD (self), query))
214 gst_query_parse_latency (query, &priv->is_live, NULL, NULL);
215 gst_query_unref (query);
216
217 return TRUE;
218 }
219
220 static gboolean
gst_vp8_decoder_update_reference(GstVp8Decoder * self,GstVp8Picture * picture)221 gst_vp8_decoder_update_reference (GstVp8Decoder * self, GstVp8Picture * picture)
222 {
223 GstVp8FrameHdr *frame_hdr = &picture->frame_hdr;
224
225 if (frame_hdr->key_frame) {
226 gst_vp8_picture_replace (&self->last_picture, picture);
227 gst_vp8_picture_replace (&self->golden_ref_picture, picture);
228 gst_vp8_picture_replace (&self->alt_ref_picture, picture);
229
230 goto done;
231 }
232
233 if (frame_hdr->refresh_alternate_frame) {
234 gst_vp8_picture_replace (&self->alt_ref_picture, picture);
235 } else {
236 switch (frame_hdr->copy_buffer_to_alternate) {
237 case 0:
238 /* do nothing */
239 break;
240 case 1:
241 gst_vp8_picture_replace (&self->alt_ref_picture, self->last_picture);
242 break;
243 case 2:
244 gst_vp8_picture_replace (&self->alt_ref_picture,
245 self->golden_ref_picture);
246 break;
247 default:
248 GST_WARNING_OBJECT (self, "unrecognized copy_buffer_to_alternate %d",
249 frame_hdr->copy_buffer_to_alternate);
250 break;
251 }
252 }
253
254 if (frame_hdr->refresh_golden_frame) {
255 gst_vp8_picture_replace (&self->golden_ref_picture, picture);
256 } else {
257 switch (frame_hdr->copy_buffer_to_golden) {
258 case 0:
259 /* do nothing */
260 break;
261 case 1:
262 gst_vp8_picture_replace (&self->golden_ref_picture, self->last_picture);
263 break;
264 case 2:
265 gst_vp8_picture_replace (&self->golden_ref_picture,
266 self->alt_ref_picture);
267 break;
268 default:
269 GST_WARNING_OBJECT (self, "unrecognized copy_buffer_to_golden %d",
270 frame_hdr->copy_buffer_to_alternate);
271 break;
272 }
273 }
274
275 if (frame_hdr->refresh_last)
276 gst_vp8_picture_replace (&self->last_picture, picture);
277
278 done:
279 gst_vp8_picture_unref (picture);
280
281 return TRUE;
282 }
283
284 static GstFlowReturn
gst_vp8_decoder_drain_internal(GstVp8Decoder * self,gboolean wait_keyframe)285 gst_vp8_decoder_drain_internal (GstVp8Decoder * self, gboolean wait_keyframe)
286 {
287 GstFlowReturn ret = GST_FLOW_OK;
288 GstVp8DecoderPrivate *priv = self->priv;
289
290 gst_vp8_decoder_drain_output_queue (self, 0, &ret);
291 gst_vp8_picture_clear (&self->last_picture);
292 gst_vp8_picture_clear (&self->golden_ref_picture);
293 gst_vp8_picture_clear (&self->alt_ref_picture);
294
295 priv->wait_keyframe = wait_keyframe;
296
297 return ret;
298 }
299
300 static GstFlowReturn
gst_vp8_decoder_finish(GstVideoDecoder * decoder)301 gst_vp8_decoder_finish (GstVideoDecoder * decoder)
302 {
303 GST_DEBUG_OBJECT (decoder, "finish");
304
305 return gst_vp8_decoder_drain_internal (GST_VP8_DECODER (decoder), TRUE);
306 }
307
308 static gboolean
gst_vp8_decoder_flush(GstVideoDecoder * decoder)309 gst_vp8_decoder_flush (GstVideoDecoder * decoder)
310 {
311 GstVp8Decoder *self = GST_VP8_DECODER (decoder);
312
313 GST_DEBUG_OBJECT (self, "flush");
314
315 gst_vp8_decoder_reset (self);
316
317 return TRUE;
318 }
319
320 static GstFlowReturn
gst_vp8_decoder_drain(GstVideoDecoder * decoder)321 gst_vp8_decoder_drain (GstVideoDecoder * decoder)
322 {
323 GST_DEBUG_OBJECT (decoder, "drain");
324
325 return gst_vp8_decoder_drain_internal (GST_VP8_DECODER (decoder), TRUE);
326 }
327
328 static void
gst_vp8_decoder_clear_output_frame(GstVp8DecoderOutputFrame * output_frame)329 gst_vp8_decoder_clear_output_frame (GstVp8DecoderOutputFrame * output_frame)
330 {
331 if (!output_frame)
332 return;
333
334 if (output_frame->frame) {
335 gst_video_decoder_release_frame (GST_VIDEO_DECODER (output_frame->self),
336 output_frame->frame);
337 output_frame->frame = NULL;
338 }
339
340 gst_vp8_picture_clear (&output_frame->picture);
341 }
342
343 static GstFlowReturn
gst_vp8_decoder_handle_frame(GstVideoDecoder * decoder,GstVideoCodecFrame * frame)344 gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder,
345 GstVideoCodecFrame * frame)
346 {
347 GstVp8Decoder *self = GST_VP8_DECODER (decoder);
348 GstVp8DecoderClass *klass = GST_VP8_DECODER_GET_CLASS (self);
349 GstVp8DecoderPrivate *priv = self->priv;
350 GstBuffer *in_buf = frame->input_buffer;
351 GstMapInfo map;
352 GstVp8FrameHdr frame_hdr;
353 GstVp8ParserResult pres;
354 GstVp8Picture *picture = NULL;
355 GstFlowReturn ret = GST_FLOW_OK;
356 GstVp8DecoderOutputFrame output_frame;
357
358 GST_LOG_OBJECT (self,
359 "handle frame, PTS: %" GST_TIME_FORMAT ", DTS: %"
360 GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (in_buf)),
361 GST_TIME_ARGS (GST_BUFFER_DTS (in_buf)));
362
363 if (!gst_buffer_map (in_buf, &map, GST_MAP_READ)) {
364 GST_ERROR_OBJECT (self, "Cannot map buffer");
365 ret = GST_FLOW_ERROR;
366 goto error;
367 }
368
369 pres = gst_vp8_parser_parse_frame_header (&priv->parser,
370 &frame_hdr, map.data, map.size);
371
372 if (pres != GST_VP8_PARSER_OK) {
373 GST_ERROR_OBJECT (self, "Cannot parser frame header");
374 ret = GST_FLOW_ERROR;
375 goto unmap_and_error;
376 }
377
378 if (priv->wait_keyframe) {
379 if (!frame_hdr.key_frame) {
380 GST_DEBUG_OBJECT (self, "Waiting initial keyframe, drop buffer %"
381 GST_PTR_FORMAT, in_buf);
382
383 gst_buffer_unmap (in_buf, &map);
384 gst_video_decoder_drop_frame (decoder, frame);
385
386 return GST_FLOW_OK;
387 }
388 }
389
390 priv->wait_keyframe = FALSE;
391
392 if (frame_hdr.key_frame) {
393 ret = gst_vp8_decoder_check_codec_change (self, &frame_hdr);
394 if (ret != GST_FLOW_OK) {
395 GST_WARNING_OBJECT (self, "Subclass cannot handle codec change");
396 goto unmap_and_error;
397 }
398 }
399
400 picture = gst_vp8_picture_new ();
401 picture->frame_hdr = frame_hdr;
402 picture->pts = GST_BUFFER_PTS (in_buf);
403 picture->data = map.data;
404 picture->size = map.size;
405 picture->system_frame_number = frame->system_frame_number;
406
407 if (klass->new_picture) {
408 ret = klass->new_picture (self, frame, picture);
409 if (ret != GST_FLOW_OK) {
410 GST_WARNING_OBJECT (self, "subclass failed to handle new picture");
411 goto unmap_and_error;
412 }
413 }
414
415 if (klass->start_picture) {
416 ret = klass->start_picture (self, picture);
417 if (ret != GST_FLOW_OK) {
418 GST_WARNING_OBJECT (self, "subclass failed to handle start picture");
419 goto unmap_and_error;
420 }
421 }
422
423 if (klass->decode_picture) {
424 ret = klass->decode_picture (self, picture, &priv->parser);
425 if (ret != GST_FLOW_OK) {
426 GST_WARNING_OBJECT (self, "subclass failed to decode current picture");
427 goto unmap_and_error;
428 }
429 }
430
431 if (klass->end_picture) {
432 ret = klass->end_picture (self, picture);
433 if (ret != GST_FLOW_OK) {
434 GST_WARNING_OBJECT (self, "subclass failed to handle end picture");
435 goto unmap_and_error;
436 }
437 }
438
439 gst_buffer_unmap (in_buf, &map);
440
441 gst_vp8_decoder_update_reference (self, gst_vp8_picture_ref (picture));
442
443 if (!picture->frame_hdr.show_frame) {
444 GST_LOG_OBJECT (self, "Decode only picture %p", picture);
445 GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame);
446
447 gst_vp8_picture_unref (picture);
448
449 ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
450 } else {
451 output_frame.frame = frame;
452 output_frame.picture = picture;
453 output_frame.self = self;
454 gst_queue_array_push_tail_struct (priv->output_queue, &output_frame);
455 }
456
457 gst_vp8_decoder_drain_output_queue (self, priv->preferred_output_delay, &ret);
458
459 if (ret == GST_FLOW_ERROR) {
460 GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
461 ("Failed to decode data"), (NULL), ret);
462 return ret;
463 }
464
465 return ret;
466
467 unmap_and_error:
468 {
469 gst_buffer_unmap (in_buf, &map);
470 goto error;
471 }
472
473 error:
474 {
475 if (picture)
476 gst_vp8_picture_unref (picture);
477
478 if (ret == GST_FLOW_ERROR) {
479 GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
480 ("Failed to decode data"), (NULL), ret);
481 }
482
483 gst_video_decoder_drop_frame (decoder, frame);
484
485 return ret;
486 }
487 }
488
489 static void
gst_vp8_decoder_drain_output_queue(GstVp8Decoder * self,guint num,GstFlowReturn * ret)490 gst_vp8_decoder_drain_output_queue (GstVp8Decoder * self, guint num,
491 GstFlowReturn * ret)
492 {
493 GstVp8DecoderPrivate *priv = self->priv;
494 GstVp8DecoderClass *klass = GST_VP8_DECODER_GET_CLASS (self);
495
496 g_assert (klass->output_picture);
497
498 while (gst_queue_array_get_length (priv->output_queue) > num) {
499 GstVp8DecoderOutputFrame *output_frame = (GstVp8DecoderOutputFrame *)
500 gst_queue_array_pop_head_struct (priv->output_queue);
501 /* Output queued frames whatever the return value is, in order to empty
502 * the queue */
503 GstFlowReturn flow_ret = klass->output_picture (self,
504 output_frame->frame, output_frame->picture);
505
506 /* Then, update @ret with new flow return value only if @ret was
507 * GST_FLOW_OK. This is to avoid pattern such that
508 * ```c
509 * GstFlowReturn my_return = GST_FLOW_OK;
510 * do something
511 *
512 * if (my_return == GST_FLOW_OK) {
513 * my_return = gst_vp8_decoder_drain_output_queue ();
514 * } else {
515 * // Ignore flow return of this method, but current `my_return` error code
516 * gst_vp8_decoder_drain_output_queue ();
517 * }
518 *
519 * return my_return;
520 * ```
521 */
522 if (*ret == GST_FLOW_OK)
523 *ret = flow_ret;
524 }
525 }
526