1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Vp9 invisible (alt-ref) frame to superframe merge bitstream filter 3cabdff1aSopenharmony_ci * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "bsf.h" 25cabdff1aSopenharmony_ci#include "bsf_internal.h" 26cabdff1aSopenharmony_ci#include "get_bits.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#define MAX_CACHE 8 29cabdff1aSopenharmony_citypedef struct VP9BSFContext { 30cabdff1aSopenharmony_ci int n_cache; 31cabdff1aSopenharmony_ci AVPacket *cache[MAX_CACHE]; 32cabdff1aSopenharmony_ci} VP9BSFContext; 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_cistatic void stats(AVPacket * const *in, int n_in, 35cabdff1aSopenharmony_ci unsigned *_max, unsigned *_sum) 36cabdff1aSopenharmony_ci{ 37cabdff1aSopenharmony_ci int n; 38cabdff1aSopenharmony_ci unsigned max = 0, sum = 0; 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci for (n = 0; n < n_in; n++) { 41cabdff1aSopenharmony_ci unsigned sz = in[n]->size; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci if (sz > max) 44cabdff1aSopenharmony_ci max = sz; 45cabdff1aSopenharmony_ci sum += sz; 46cabdff1aSopenharmony_ci } 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci *_max = max; 49cabdff1aSopenharmony_ci *_sum = sum; 50cabdff1aSopenharmony_ci} 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_cistatic int merge_superframe(AVPacket * const *in, int n_in, AVPacket *out) 53cabdff1aSopenharmony_ci{ 54cabdff1aSopenharmony_ci unsigned max, sum, mag, marker, n, sz; 55cabdff1aSopenharmony_ci uint8_t *ptr; 56cabdff1aSopenharmony_ci int res; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci stats(in, n_in, &max, &sum); 59cabdff1aSopenharmony_ci mag = av_log2(max) >> 3; 60cabdff1aSopenharmony_ci marker = 0xC0 + (mag << 3) + (n_in - 1); 61cabdff1aSopenharmony_ci sz = sum + 2 + (mag + 1) * n_in; 62cabdff1aSopenharmony_ci res = av_new_packet(out, sz); 63cabdff1aSopenharmony_ci if (res < 0) 64cabdff1aSopenharmony_ci return res; 65cabdff1aSopenharmony_ci ptr = out->data; 66cabdff1aSopenharmony_ci for (n = 0; n < n_in; n++) { 67cabdff1aSopenharmony_ci memcpy(ptr, in[n]->data, in[n]->size); 68cabdff1aSopenharmony_ci ptr += in[n]->size; 69cabdff1aSopenharmony_ci } 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci#define wloop(mag, wr) \ 72cabdff1aSopenharmony_ci do { \ 73cabdff1aSopenharmony_ci for (n = 0; n < n_in; n++) { \ 74cabdff1aSopenharmony_ci wr; \ 75cabdff1aSopenharmony_ci ptr += mag + 1; \ 76cabdff1aSopenharmony_ci } \ 77cabdff1aSopenharmony_ci } while (0) 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci // write superframe with marker 110[mag:2][nframes:3] 80cabdff1aSopenharmony_ci *ptr++ = marker; 81cabdff1aSopenharmony_ci switch (mag) { 82cabdff1aSopenharmony_ci case 0: 83cabdff1aSopenharmony_ci wloop(mag, *ptr = in[n]->size); 84cabdff1aSopenharmony_ci break; 85cabdff1aSopenharmony_ci case 1: 86cabdff1aSopenharmony_ci wloop(mag, AV_WL16(ptr, in[n]->size)); 87cabdff1aSopenharmony_ci break; 88cabdff1aSopenharmony_ci case 2: 89cabdff1aSopenharmony_ci wloop(mag, AV_WL24(ptr, in[n]->size)); 90cabdff1aSopenharmony_ci break; 91cabdff1aSopenharmony_ci case 3: 92cabdff1aSopenharmony_ci wloop(mag, AV_WL32(ptr, in[n]->size)); 93cabdff1aSopenharmony_ci break; 94cabdff1aSopenharmony_ci } 95cabdff1aSopenharmony_ci *ptr++ = marker; 96cabdff1aSopenharmony_ci av_assert0(ptr == &out->data[out->size]); 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci return 0; 99cabdff1aSopenharmony_ci} 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_cistatic int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *pkt) 102cabdff1aSopenharmony_ci{ 103cabdff1aSopenharmony_ci GetBitContext gb; 104cabdff1aSopenharmony_ci VP9BSFContext *s = ctx->priv_data; 105cabdff1aSopenharmony_ci int res, invisible, profile, marker, uses_superframe_syntax = 0, n; 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci res = ff_bsf_get_packet_ref(ctx, pkt); 108cabdff1aSopenharmony_ci if (res < 0) 109cabdff1aSopenharmony_ci return res; 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci if (!pkt->size) { 112cabdff1aSopenharmony_ci /* In case the cache is empty we can pass side-data-only packets 113cabdff1aSopenharmony_ci * through unchanged. Otherwise, such a packet makes no sense. */ 114cabdff1aSopenharmony_ci if (!s->n_cache) 115cabdff1aSopenharmony_ci return 0; 116cabdff1aSopenharmony_ci res = AVERROR_INVALIDDATA; 117cabdff1aSopenharmony_ci goto done; 118cabdff1aSopenharmony_ci } 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci marker = pkt->data[pkt->size - 1]; 121cabdff1aSopenharmony_ci if ((marker & 0xe0) == 0xc0) { 122cabdff1aSopenharmony_ci int nbytes = 1 + ((marker >> 3) & 0x3); 123cabdff1aSopenharmony_ci int n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci uses_superframe_syntax = pkt->size >= idx_sz && pkt->data[pkt->size - idx_sz] == marker; 126cabdff1aSopenharmony_ci } 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci if ((res = init_get_bits8(&gb, pkt->data, pkt->size)) < 0) 129cabdff1aSopenharmony_ci goto done; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci get_bits(&gb, 2); // frame marker 132cabdff1aSopenharmony_ci profile = get_bits1(&gb); 133cabdff1aSopenharmony_ci profile |= get_bits1(&gb) << 1; 134cabdff1aSopenharmony_ci if (profile == 3) profile += get_bits1(&gb); 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci if (get_bits1(&gb)) { 137cabdff1aSopenharmony_ci invisible = 0; 138cabdff1aSopenharmony_ci } else { 139cabdff1aSopenharmony_ci get_bits1(&gb); // keyframe 140cabdff1aSopenharmony_ci invisible = !get_bits1(&gb); 141cabdff1aSopenharmony_ci } 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci if (uses_superframe_syntax && s->n_cache > 0) { 144cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 145cabdff1aSopenharmony_ci "Mixing of superframe syntax and naked VP9 frames not supported\n"); 146cabdff1aSopenharmony_ci res = AVERROR(ENOSYS); 147cabdff1aSopenharmony_ci goto done; 148cabdff1aSopenharmony_ci } else if ((!invisible || uses_superframe_syntax) && !s->n_cache) { 149cabdff1aSopenharmony_ci // passthrough 150cabdff1aSopenharmony_ci return 0; 151cabdff1aSopenharmony_ci } else if (s->n_cache + 1 >= MAX_CACHE) { 152cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 153cabdff1aSopenharmony_ci "Too many invisible frames\n"); 154cabdff1aSopenharmony_ci res = AVERROR_INVALIDDATA; 155cabdff1aSopenharmony_ci goto done; 156cabdff1aSopenharmony_ci } 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci av_packet_move_ref(s->cache[s->n_cache++], pkt); 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci if (invisible) { 161cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci av_assert0(s->n_cache > 0); 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci // build superframe 166cabdff1aSopenharmony_ci if ((res = merge_superframe(s->cache, s->n_cache, pkt)) < 0) 167cabdff1aSopenharmony_ci goto done; 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci res = av_packet_copy_props(pkt, s->cache[s->n_cache - 1]); 170cabdff1aSopenharmony_ci if (res < 0) 171cabdff1aSopenharmony_ci goto done; 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_ci for (n = 0; n < s->n_cache; n++) 174cabdff1aSopenharmony_ci av_packet_unref(s->cache[n]); 175cabdff1aSopenharmony_ci s->n_cache = 0; 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_cidone: 178cabdff1aSopenharmony_ci if (res < 0) 179cabdff1aSopenharmony_ci av_packet_unref(pkt); 180cabdff1aSopenharmony_ci return res; 181cabdff1aSopenharmony_ci} 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_cistatic int vp9_superframe_init(AVBSFContext *ctx) 184cabdff1aSopenharmony_ci{ 185cabdff1aSopenharmony_ci VP9BSFContext *s = ctx->priv_data; 186cabdff1aSopenharmony_ci int n; 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci // alloc cache packets 189cabdff1aSopenharmony_ci for (n = 0; n < MAX_CACHE; n++) { 190cabdff1aSopenharmony_ci s->cache[n] = av_packet_alloc(); 191cabdff1aSopenharmony_ci if (!s->cache[n]) 192cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 193cabdff1aSopenharmony_ci } 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci return 0; 196cabdff1aSopenharmony_ci} 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_cistatic void vp9_superframe_flush(AVBSFContext *ctx) 199cabdff1aSopenharmony_ci{ 200cabdff1aSopenharmony_ci VP9BSFContext *s = ctx->priv_data; 201cabdff1aSopenharmony_ci int n; 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci // unref cached data 204cabdff1aSopenharmony_ci for (n = 0; n < s->n_cache; n++) 205cabdff1aSopenharmony_ci av_packet_unref(s->cache[n]); 206cabdff1aSopenharmony_ci s->n_cache = 0; 207cabdff1aSopenharmony_ci} 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_cistatic void vp9_superframe_close(AVBSFContext *ctx) 210cabdff1aSopenharmony_ci{ 211cabdff1aSopenharmony_ci VP9BSFContext *s = ctx->priv_data; 212cabdff1aSopenharmony_ci int n; 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci // free cached data 215cabdff1aSopenharmony_ci for (n = 0; n < MAX_CACHE; n++) 216cabdff1aSopenharmony_ci av_packet_free(&s->cache[n]); 217cabdff1aSopenharmony_ci} 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_cistatic const enum AVCodecID codec_ids[] = { 220cabdff1aSopenharmony_ci AV_CODEC_ID_VP9, AV_CODEC_ID_NONE, 221cabdff1aSopenharmony_ci}; 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_vp9_superframe_bsf = { 224cabdff1aSopenharmony_ci .p.name = "vp9_superframe", 225cabdff1aSopenharmony_ci .p.codec_ids = codec_ids, 226cabdff1aSopenharmony_ci .priv_data_size = sizeof(VP9BSFContext), 227cabdff1aSopenharmony_ci .filter = vp9_superframe_filter, 228cabdff1aSopenharmony_ci .init = vp9_superframe_init, 229cabdff1aSopenharmony_ci .flush = vp9_superframe_flush, 230cabdff1aSopenharmony_ci .close = vp9_superframe_close, 231cabdff1aSopenharmony_ci}; 232