GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/vp9_raw_reorder_bsf.c Lines: 0 194 0.0 %
Date: 2020-09-25 14:59:26 Branches: 0 132 0.0 %

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