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