Browse code

vp9: Add bsf to fix reordering in raw streams

Takes a raw input stream containing frames with correct timestamps but
possibly out of order and inserts additional show-existing-frame
packets to correct the ordering.

(cherry picked from commit 34e051d16850701694410a0e72e0e4ff3a5ec293)
(cherry picked from commit b43b95f4789b6e60f9684918fd3c0a5f3f18aef6)

Also converted from bitstream to get_bits.

Mark Thompson authored on 2017/01/10 08:08:49
Showing 5 changed files
... ...
@@ -277,4 +277,9 @@ was split from its visible counterpart.
277 277
 
278 278
 Split VP9 superframes into single frames.
279 279
 
280
+@section vp9_raw_reorder
281
+
282
+Given a VP9 stream with correct timestamps but possibly out of order,
283
+insert additional show-existing-frame packets to correct the ordering.
284
+
280 285
 @c man end BITSTREAM FILTERS
... ...
@@ -998,6 +998,7 @@ OBJS-$(CONFIG_NOISE_BSF)                  += noise_bsf.o
998 998
 OBJS-$(CONFIG_NULL_BSF)                   += null_bsf.o
999 999
 OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF)       += remove_extradata_bsf.o
1000 1000
 OBJS-$(CONFIG_TEXT2MOVSUB_BSF)            += movsub_bsf.o
1001
+OBJS-$(CONFIG_VP9_RAW_REORDER_BSF)        += vp9_raw_reorder_bsf.o
1001 1002
 OBJS-$(CONFIG_VP9_SUPERFRAME_BSF)         += vp9_superframe_bsf.o
1002 1003
 OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF)   += vp9_superframe_split_bsf.o
1003 1004
 
... ...
@@ -41,6 +41,7 @@ extern const AVBitStreamFilter ff_noise_bsf;
41 41
 extern const AVBitStreamFilter ff_null_bsf;
42 42
 extern const AVBitStreamFilter ff_remove_extradata_bsf;
43 43
 extern const AVBitStreamFilter ff_text2movsub_bsf;
44
+extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf;
44 45
 extern const AVBitStreamFilter ff_vp9_superframe_bsf;
45 46
 extern const AVBitStreamFilter ff_vp9_superframe_split_bsf;
46 47
 
... ...
@@ -29,7 +29,7 @@
29 29
 
30 30
 #define LIBAVCODEC_VERSION_MAJOR  57
31 31
 #define LIBAVCODEC_VERSION_MINOR  99
32
-#define LIBAVCODEC_VERSION_MICRO 100
32
+#define LIBAVCODEC_VERSION_MICRO 101
33 33
 
34 34
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
35 35
                                                LIBAVCODEC_VERSION_MINOR, \
36 36
new file mode 100644
... ...
@@ -0,0 +1,407 @@
0
+/*
1
+ * This file is part of FFmpeg.
2
+ *
3
+ * FFmpeg is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2.1 of the License, or (at your option) any later version.
7
+ *
8
+ * FFmpeg is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with FFmpeg; if not, write to the Free Software
15
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+ */
17
+
18
+#include "libavutil/avassert.h"
19
+#include "libavutil/intmath.h"
20
+#include "libavutil/log.h"
21
+#include "libavutil/mem.h"
22
+#include "libavutil/opt.h"
23
+
24
+#include "bsf.h"
25
+#include "get_bits.h"
26
+#include "put_bits.h"
27
+
28
+#define FRAME_SLOTS 8
29
+
30
+typedef struct VP9RawReorderFrame {
31
+    AVPacket    *packet;
32
+    int          needs_output;
33
+    int          needs_display;
34
+
35
+    int64_t      pts;
36
+    int64_t      sequence;
37
+    unsigned int slots;
38
+
39
+    unsigned int profile;
40
+
41
+    unsigned int show_existing_frame;
42
+    unsigned int frame_to_show;
43
+
44
+    unsigned int frame_type;
45
+    unsigned int show_frame;
46
+    unsigned int refresh_frame_flags;
47
+} VP9RawReorderFrame;
48
+
49
+typedef struct VP9RawReorderContext {
50
+    int64_t sequence;
51
+    VP9RawReorderFrame *slot[FRAME_SLOTS];
52
+    VP9RawReorderFrame *next_frame;
53
+} VP9RawReorderContext;
54
+
55
+static void vp9_raw_reorder_frame_free(VP9RawReorderFrame **frame)
56
+{
57
+    if (*frame)
58
+        av_packet_free(&(*frame)->packet);
59
+    av_freep(frame);
60
+}
61
+
62
+static void vp9_raw_reorder_clear_slot(VP9RawReorderContext *ctx, int s)
63
+{
64
+    if (ctx->slot[s]) {
65
+        ctx->slot[s]->slots &= ~(1 << s);
66
+        if (ctx->slot[s]->slots == 0)
67
+            vp9_raw_reorder_frame_free(&ctx->slot[s]);
68
+        else
69
+            ctx->slot[s] = NULL;
70
+    }
71
+}
72
+
73
+static int vp9_raw_reorder_frame_parse(AVBSFContext *bsf, VP9RawReorderFrame *frame)
74
+{
75
+    GetBitContext bc;
76
+    int err;
77
+
78
+    unsigned int frame_marker;
79
+    unsigned int profile_low_bit, profile_high_bit, reserved_zero;
80
+    unsigned int error_resilient_mode;
81
+    unsigned int frame_sync_code;
82
+
83
+    err = init_get_bits(&bc, frame->packet->data, 8 * frame->packet->size);
84
+    if (err)
85
+        return err;
86
+
87
+    frame_marker = get_bits(&bc, 2);
88
+    if (frame_marker != 2) {
89
+        av_log(bsf, AV_LOG_ERROR, "Invalid frame marker: %u.\n",
90
+               frame_marker);
91
+        return AVERROR_INVALIDDATA;
92
+    }
93
+
94
+    profile_low_bit  = get_bits1(&bc);
95
+    profile_high_bit = get_bits1(&bc);
96
+    frame->profile = (profile_high_bit << 1) | profile_low_bit;
97
+    if (frame->profile == 3) {
98
+        reserved_zero = get_bits1(&bc);
99
+        if (reserved_zero != 0) {
100
+            av_log(bsf, AV_LOG_ERROR, "Profile reserved_zero bit set: "
101
+                   "unsupported profile or invalid bitstream.\n");
102
+            return AVERROR_INVALIDDATA;
103
+        }
104
+    }
105
+
106
+    frame->show_existing_frame = get_bits1(&bc);
107
+    if (frame->show_existing_frame) {
108
+        frame->frame_to_show = get_bits(&bc, 3);
109
+        return 0;
110
+    }
111
+
112
+    frame->frame_type = get_bits1(&bc);
113
+    frame->show_frame = get_bits1(&bc);
114
+    error_resilient_mode = get_bits1(&bc);
115
+
116
+    if (frame->frame_type == 0) {
117
+        frame_sync_code = get_bits(&bc, 24);
118
+        if (frame_sync_code != 0x498342) {
119
+            av_log(bsf, AV_LOG_ERROR, "Invalid frame sync code: %06x.\n",
120
+                   frame_sync_code);
121
+            return AVERROR_INVALIDDATA;
122
+        }
123
+        frame->refresh_frame_flags = 0xff;
124
+    } else {
125
+        unsigned int intra_only;
126
+
127
+        if (frame->show_frame == 0)
128
+            intra_only = get_bits1(&bc);
129
+        else
130
+            intra_only = 0;
131
+        if (error_resilient_mode == 0) {
132
+            // reset_frame_context
133
+            skip_bits(&bc, 2);
134
+        }
135
+        if (intra_only) {
136
+            frame_sync_code = get_bits(&bc, 24);
137
+            if (frame_sync_code != 0x498342) {
138
+                av_log(bsf, AV_LOG_ERROR, "Invalid frame sync code: "
139
+                       "%06x.\n", frame_sync_code);
140
+                return AVERROR_INVALIDDATA;
141
+            }
142
+            if (frame->profile > 0) {
143
+                unsigned int color_space;
144
+                if (frame->profile >= 2) {
145
+                    // ten_or_twelve_bit
146
+                    skip_bits(&bc, 1);
147
+                }
148
+                color_space = get_bits(&bc, 3);
149
+                if (color_space != 7 /* CS_RGB */) {
150
+                    // color_range
151
+                    skip_bits(&bc, 1);
152
+                    if (frame->profile == 1 || frame->profile == 3) {
153
+                        // subsampling
154
+                        skip_bits(&bc, 3);
155
+                    }
156
+                } else {
157
+                    if (frame->profile == 1 || frame->profile == 3)
158
+                        skip_bits(&bc, 1);
159
+                }
160
+            }
161
+            frame->refresh_frame_flags = get_bits(&bc, 8);
162
+        } else {
163
+            frame->refresh_frame_flags = get_bits(&bc, 8);
164
+        }
165
+    }
166
+
167
+    return 0;
168
+}
169
+
170
+static int vp9_raw_reorder_make_output(AVBSFContext *bsf,
171
+                                   AVPacket *out,
172
+                                   VP9RawReorderFrame *last_frame)
173
+{
174
+    VP9RawReorderContext *ctx = bsf->priv_data;
175
+    VP9RawReorderFrame *next_output = last_frame,
176
+                      *next_display = last_frame, *frame;
177
+    int s, err;
178
+
179
+    for (s = 0; s < FRAME_SLOTS; s++) {
180
+        frame = ctx->slot[s];
181
+        if (!frame)
182
+            continue;
183
+        if (frame->needs_output && (!next_output ||
184
+            frame->sequence < next_output->sequence))
185
+            next_output = frame;
186
+        if (frame->needs_display && (!next_display ||
187
+            frame->pts < next_display->pts))
188
+            next_display = frame;
189
+    }
190
+
191
+    if (!next_output && !next_display)
192
+        return AVERROR_EOF;
193
+
194
+    if (!next_display || (next_output &&
195
+        next_output->sequence < next_display->sequence))
196
+        frame = next_output;
197
+    else
198
+        frame = next_display;
199
+
200
+    if (frame->needs_output && frame->needs_display &&
201
+        next_output == next_display) {
202
+        av_log(bsf, AV_LOG_DEBUG, "Output and display frame "
203
+               "%"PRId64" (%"PRId64") in order.\n",
204
+               frame->sequence, frame->pts);
205
+
206
+        av_packet_move_ref(out, frame->packet);
207
+
208
+        frame->needs_output = frame->needs_display = 0;
209
+    } else if (frame->needs_output) {
210
+        if (frame->needs_display) {
211
+            av_log(bsf, AV_LOG_DEBUG, "Output frame %"PRId64" "
212
+                   "(%"PRId64") for later display.\n",
213
+                   frame->sequence, frame->pts);
214
+        } else {
215
+            av_log(bsf, AV_LOG_DEBUG, "Output unshown frame "
216
+                   "%"PRId64" (%"PRId64") to keep order.\n",
217
+                   frame->sequence, frame->pts);
218
+        }
219
+
220
+        av_packet_move_ref(out, frame->packet);
221
+        out->pts = out->dts;
222
+
223
+        frame->needs_output = 0;
224
+    } else {
225
+        PutBitContext pb;
226
+
227
+        av_assert0(!frame->needs_output && frame->needs_display);
228
+
229
+        if (frame->slots == 0) {
230
+            av_log(bsf, AV_LOG_ERROR, "Attempting to display frame "
231
+                   "which is no longer available?\n");
232
+            frame->needs_display = 0;
233
+            return AVERROR_INVALIDDATA;
234
+        }
235
+
236
+        s = ff_ctz(frame->slots);
237
+        av_assert0(s < FRAME_SLOTS);
238
+
239
+        av_log(bsf, AV_LOG_DEBUG, "Display frame %"PRId64" "
240
+               "(%"PRId64") from slot %d.\n",
241
+               frame->sequence, frame->pts, s);
242
+
243
+        err = av_new_packet(out, 2);
244
+        if (err < 0)
245
+            return err;
246
+
247
+        init_put_bits(&pb, out->data, 2);
248
+
249
+        // frame_marker
250
+        put_bits(&pb, 2, 2);
251
+        // profile_low_bit
252
+        put_bits(&pb, 1, frame->profile & 1);
253
+        // profile_high_bit
254
+        put_bits(&pb, 1, (frame->profile >> 1) & 1);
255
+        if (frame->profile == 3) {
256
+            // reserved_zero
257
+            put_bits(&pb, 1, 0);
258
+        }
259
+        // show_existing_frame
260
+        put_bits(&pb, 1, 1);
261
+        // frame_to_show_map_idx
262
+        put_bits(&pb, 3, s);
263
+
264
+        while (put_bits_count(&pb) < 16)
265
+            put_bits(&pb, 1, 0);
266
+
267
+        flush_put_bits(&pb);
268
+        out->pts = out->dts = frame->pts;
269
+
270
+        frame->needs_display = 0;
271
+    }
272
+
273
+    return 0;
274
+}
275
+
276
+static int vp9_raw_reorder_filter(AVBSFContext *bsf, AVPacket *out)
277
+{
278
+    VP9RawReorderContext *ctx = bsf->priv_data;
279
+    VP9RawReorderFrame *frame;
280
+    AVPacket *in;
281
+    int err, s;
282
+
283
+    if (ctx->next_frame) {
284
+        frame = ctx->next_frame;
285
+
286
+    } else {
287
+        err = ff_bsf_get_packet(bsf, &in);
288
+        if (err < 0) {
289
+            if (err == AVERROR_EOF)
290
+                return vp9_raw_reorder_make_output(bsf, out, NULL);
291
+            return err;
292
+        }
293
+
294
+        if (in->data[in->size - 1] & 0xe0 == 0xc0) {
295
+            av_log(bsf, AV_LOG_ERROR, "Input in superframes is not "
296
+                   "supported.\n");
297
+            av_packet_free(&in);
298
+            return AVERROR(ENOSYS);
299
+        }
300
+
301
+        frame = av_mallocz(sizeof(*frame));
302
+        if (!frame) {
303
+            av_packet_free(&in);
304
+            return AVERROR(ENOMEM);
305
+        }
306
+
307
+        frame->packet   = in;
308
+        frame->pts      = in->pts;
309
+        frame->sequence = ++ctx->sequence;
310
+        err = vp9_raw_reorder_frame_parse(bsf, frame);
311
+        if (err) {
312
+            av_log(bsf, AV_LOG_ERROR, "Failed to parse input "
313
+                   "frame: %d.\n", err);
314
+            goto fail;
315
+        }
316
+
317
+        frame->needs_output  = 1;
318
+        frame->needs_display = frame->pts != AV_NOPTS_VALUE;
319
+
320
+        if (frame->show_existing_frame)
321
+            av_log(bsf, AV_LOG_DEBUG, "Show frame %"PRId64" "
322
+                   "(%"PRId64"): show %u.\n", frame->sequence,
323
+                   frame->pts, frame->frame_to_show);
324
+        else
325
+            av_log(bsf, AV_LOG_DEBUG, "New frame %"PRId64" "
326
+                   "(%"PRId64"): type %u show %u refresh %02x.\n",
327
+                   frame->sequence, frame->pts, frame->frame_type,
328
+                   frame->show_frame, frame->refresh_frame_flags);
329
+
330
+        ctx->next_frame = frame;
331
+    }
332
+
333
+    for (s = 0; s < FRAME_SLOTS; s++) {
334
+        if (!(frame->refresh_frame_flags & (1 << s)))
335
+            continue;
336
+        if (ctx->slot[s] && ctx->slot[s]->needs_display &&
337
+            ctx->slot[s]->slots == (1 << s)) {
338
+            // We are overwriting this slot, which is last reference
339
+            // to the frame previously present in it.  In order to be
340
+            // a valid stream, that frame must already have been
341
+            // displayed before the pts of the current frame.
342
+            err = vp9_raw_reorder_make_output(bsf, out, ctx->slot[s]);
343
+            if (err < 0) {
344
+                av_log(bsf, AV_LOG_ERROR, "Failed to create "
345
+                       "output overwriting slot %d: %d.\n",
346
+                       s, err);
347
+                // Clear the slot anyway, so we don't end up
348
+                // in an infinite loop.
349
+                vp9_raw_reorder_clear_slot(ctx, s);
350
+                return AVERROR_INVALIDDATA;
351
+            }
352
+            return 0;
353
+        }
354
+        vp9_raw_reorder_clear_slot(ctx, s);
355
+    }
356
+
357
+    for (s = 0; s < FRAME_SLOTS; s++) {
358
+        if (!(frame->refresh_frame_flags & (1 << s)))
359
+            continue;
360
+        ctx->slot[s] = frame;
361
+    }
362
+    frame->slots = frame->refresh_frame_flags;
363
+
364
+    if (!frame->refresh_frame_flags) {
365
+        err = vp9_raw_reorder_make_output(bsf, out, frame);
366
+        if (err < 0) {
367
+            av_log(bsf, AV_LOG_ERROR, "Failed to create output "
368
+                   "for transient frame.\n");
369
+            ctx->next_frame = NULL;
370
+            return AVERROR_INVALIDDATA;
371
+        }
372
+        if (!frame->needs_display) {
373
+            vp9_raw_reorder_frame_free(&frame);
374
+            ctx->next_frame = NULL;
375
+        }
376
+        return 0;
377
+    }
378
+
379
+    ctx->next_frame = NULL;
380
+    return AVERROR(EAGAIN);
381
+
382
+fail:
383
+    vp9_raw_reorder_frame_free(&frame);
384
+    return err;
385
+}
386
+
387
+static void vp9_raw_reorder_close(AVBSFContext *bsf)
388
+{
389
+    VP9RawReorderContext *ctx = bsf->priv_data;
390
+    int s;
391
+
392
+    for (s = 0; s < FRAME_SLOTS; s++)
393
+        vp9_raw_reorder_clear_slot(ctx, s);
394
+}
395
+
396
+static const enum AVCodecID vp9_raw_reorder_codec_ids[] = {
397
+    AV_CODEC_ID_VP9, AV_CODEC_ID_NONE,
398
+};
399
+
400
+const AVBitStreamFilter ff_vp9_raw_reorder_bsf = {
401
+    .name           = "vp9_raw_reorder",
402
+    .priv_data_size = sizeof(VP9RawReorderContext),
403
+    .close          = &vp9_raw_reorder_close,
404
+    .filter         = &vp9_raw_reorder_filter,
405
+    .codec_ids      = vp9_raw_reorder_codec_ids,
406
+};