1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "libavutil/log.h" 22cabdff1aSopenharmony_ci#include "libavutil/opt.h" 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "av1_parse.h" 25cabdff1aSopenharmony_ci#include "bsf.h" 26cabdff1aSopenharmony_ci#include "bsf_internal.h" 27cabdff1aSopenharmony_ci#include "h264.h" 28cabdff1aSopenharmony_ci#include "hevc.h" 29cabdff1aSopenharmony_ci#include "startcode.h" 30cabdff1aSopenharmony_ci#include "vc1_common.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_cienum RemoveFreq { 33cabdff1aSopenharmony_ci REMOVE_FREQ_KEYFRAME, 34cabdff1aSopenharmony_ci REMOVE_FREQ_ALL, 35cabdff1aSopenharmony_ci REMOVE_FREQ_NONKEYFRAME, 36cabdff1aSopenharmony_ci}; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci#define START_CODE 0x000001 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_citypedef struct RemoveExtradataContext { 41cabdff1aSopenharmony_ci const AVClass *class; 42cabdff1aSopenharmony_ci int freq; 43cabdff1aSopenharmony_ci} RemoveExtradataContext; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_cistatic int av1_split(const uint8_t *buf, int buf_size, void *logctx) 46cabdff1aSopenharmony_ci{ 47cabdff1aSopenharmony_ci AV1OBU obu; 48cabdff1aSopenharmony_ci const uint8_t *ptr = buf, *end = buf + buf_size; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci while (ptr < end) { 51cabdff1aSopenharmony_ci int len = ff_av1_extract_obu(&obu, ptr, buf_size, logctx); 52cabdff1aSopenharmony_ci if (len < 0) 53cabdff1aSopenharmony_ci break; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci if (obu.type == AV1_OBU_FRAME_HEADER || 56cabdff1aSopenharmony_ci obu.type == AV1_OBU_FRAME) { 57cabdff1aSopenharmony_ci return ptr - buf; 58cabdff1aSopenharmony_ci } 59cabdff1aSopenharmony_ci ptr += len; 60cabdff1aSopenharmony_ci buf_size -= len; 61cabdff1aSopenharmony_ci } 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci return 0; 64cabdff1aSopenharmony_ci} 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_cistatic int h264_split(const uint8_t *buf, int buf_size) 67cabdff1aSopenharmony_ci{ 68cabdff1aSopenharmony_ci const uint8_t *ptr = buf, *end = buf + buf_size; 69cabdff1aSopenharmony_ci uint32_t state = -1; 70cabdff1aSopenharmony_ci int has_sps = 0; 71cabdff1aSopenharmony_ci int has_pps = 0; 72cabdff1aSopenharmony_ci int nalu_type; 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci while (ptr < end) { 75cabdff1aSopenharmony_ci ptr = avpriv_find_start_code(ptr, end, &state); 76cabdff1aSopenharmony_ci if ((state & 0xFFFFFF00) != 0x100) 77cabdff1aSopenharmony_ci break; 78cabdff1aSopenharmony_ci nalu_type = state & 0x1F; 79cabdff1aSopenharmony_ci if (nalu_type == H264_NAL_SPS) { 80cabdff1aSopenharmony_ci has_sps = 1; 81cabdff1aSopenharmony_ci } else if (nalu_type == H264_NAL_PPS) 82cabdff1aSopenharmony_ci has_pps = 1; 83cabdff1aSopenharmony_ci /* else if (nalu_type == 0x01 || 84cabdff1aSopenharmony_ci * nalu_type == 0x02 || 85cabdff1aSopenharmony_ci * nalu_type == 0x05) { 86cabdff1aSopenharmony_ci * } 87cabdff1aSopenharmony_ci */ 88cabdff1aSopenharmony_ci else if ((nalu_type != H264_NAL_SEI || has_pps) && 89cabdff1aSopenharmony_ci nalu_type != H264_NAL_AUD && nalu_type != H264_NAL_SPS_EXT && 90cabdff1aSopenharmony_ci nalu_type != 0x0f) { 91cabdff1aSopenharmony_ci if (has_sps) { 92cabdff1aSopenharmony_ci while (ptr - 4 > buf && ptr[-5] == 0) 93cabdff1aSopenharmony_ci ptr--; 94cabdff1aSopenharmony_ci return ptr - 4 - buf; 95cabdff1aSopenharmony_ci } 96cabdff1aSopenharmony_ci } 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci return 0; 100cabdff1aSopenharmony_ci} 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci// Split after the parameter sets at the beginning of the stream if they exist. 103cabdff1aSopenharmony_cistatic int hevc_split(const uint8_t *buf, int buf_size) 104cabdff1aSopenharmony_ci{ 105cabdff1aSopenharmony_ci const uint8_t *ptr = buf, *end = buf + buf_size; 106cabdff1aSopenharmony_ci uint32_t state = -1; 107cabdff1aSopenharmony_ci int has_vps = 0; 108cabdff1aSopenharmony_ci int has_sps = 0; 109cabdff1aSopenharmony_ci int has_pps = 0; 110cabdff1aSopenharmony_ci int nut; 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci while (ptr < end) { 113cabdff1aSopenharmony_ci ptr = avpriv_find_start_code(ptr, end, &state); 114cabdff1aSopenharmony_ci if ((state >> 8) != START_CODE) 115cabdff1aSopenharmony_ci break; 116cabdff1aSopenharmony_ci nut = (state >> 1) & 0x3F; 117cabdff1aSopenharmony_ci if (nut == HEVC_NAL_VPS) 118cabdff1aSopenharmony_ci has_vps = 1; 119cabdff1aSopenharmony_ci else if (nut == HEVC_NAL_SPS) 120cabdff1aSopenharmony_ci has_sps = 1; 121cabdff1aSopenharmony_ci else if (nut == HEVC_NAL_PPS) 122cabdff1aSopenharmony_ci has_pps = 1; 123cabdff1aSopenharmony_ci else if ((nut != HEVC_NAL_SEI_PREFIX || has_pps) && 124cabdff1aSopenharmony_ci nut != HEVC_NAL_AUD) { 125cabdff1aSopenharmony_ci if (has_vps && has_sps) { 126cabdff1aSopenharmony_ci while (ptr - 4 > buf && ptr[-5] == 0) 127cabdff1aSopenharmony_ci ptr--; 128cabdff1aSopenharmony_ci return ptr - 4 - buf; 129cabdff1aSopenharmony_ci } 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci } 132cabdff1aSopenharmony_ci return 0; 133cabdff1aSopenharmony_ci} 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_cistatic int mpegvideo_split(const uint8_t *buf, int buf_size) 136cabdff1aSopenharmony_ci{ 137cabdff1aSopenharmony_ci uint32_t state = -1; 138cabdff1aSopenharmony_ci int found = 0; 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci for (int i = 0; i < buf_size; i++) { 141cabdff1aSopenharmony_ci state = (state << 8) | buf[i]; 142cabdff1aSopenharmony_ci if (state == 0x1B3) { 143cabdff1aSopenharmony_ci found = 1; 144cabdff1aSopenharmony_ci } else if (found && state != 0x1B5 && state < 0x200 && state >= 0x100) 145cabdff1aSopenharmony_ci return i - 3; 146cabdff1aSopenharmony_ci } 147cabdff1aSopenharmony_ci return 0; 148cabdff1aSopenharmony_ci} 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_cistatic int mpeg4video_split(const uint8_t *buf, int buf_size) 151cabdff1aSopenharmony_ci{ 152cabdff1aSopenharmony_ci const uint8_t *ptr = buf, *end = buf + buf_size; 153cabdff1aSopenharmony_ci uint32_t state = -1; 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci while (ptr < end) { 156cabdff1aSopenharmony_ci ptr = avpriv_find_start_code(ptr, end, &state); 157cabdff1aSopenharmony_ci if (state == 0x1B3 || state == 0x1B6) 158cabdff1aSopenharmony_ci return ptr - 4 - buf; 159cabdff1aSopenharmony_ci } 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci return 0; 162cabdff1aSopenharmony_ci} 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_cistatic int vc1_split(const uint8_t *buf, int buf_size) 165cabdff1aSopenharmony_ci{ 166cabdff1aSopenharmony_ci const uint8_t *ptr = buf, *end = buf + buf_size; 167cabdff1aSopenharmony_ci uint32_t state = -1; 168cabdff1aSopenharmony_ci int charged = 0; 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci while (ptr < end) { 171cabdff1aSopenharmony_ci ptr = avpriv_find_start_code(ptr, end, &state); 172cabdff1aSopenharmony_ci if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) { 173cabdff1aSopenharmony_ci charged = 1; 174cabdff1aSopenharmony_ci } else if (charged && IS_MARKER(state)) 175cabdff1aSopenharmony_ci return ptr - 4 - buf; 176cabdff1aSopenharmony_ci } 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci return 0; 179cabdff1aSopenharmony_ci} 180cabdff1aSopenharmony_ci 181cabdff1aSopenharmony_cistatic int remove_extradata(AVBSFContext *ctx, AVPacket *pkt) 182cabdff1aSopenharmony_ci{ 183cabdff1aSopenharmony_ci RemoveExtradataContext *s = ctx->priv_data; 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci int ret; 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci ret = ff_bsf_get_packet_ref(ctx, pkt); 188cabdff1aSopenharmony_ci if (ret < 0) 189cabdff1aSopenharmony_ci return ret; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci if (s->freq == REMOVE_FREQ_ALL || 192cabdff1aSopenharmony_ci (s->freq == REMOVE_FREQ_NONKEYFRAME && !(pkt->flags & AV_PKT_FLAG_KEY)) || 193cabdff1aSopenharmony_ci (s->freq == REMOVE_FREQ_KEYFRAME && pkt->flags & AV_PKT_FLAG_KEY)) { 194cabdff1aSopenharmony_ci int i; 195cabdff1aSopenharmony_ci 196cabdff1aSopenharmony_ci switch (ctx->par_in->codec_id) { 197cabdff1aSopenharmony_ci case AV_CODEC_ID_AV1: 198cabdff1aSopenharmony_ci i = av1_split(pkt->data, pkt->size, ctx); 199cabdff1aSopenharmony_ci break; 200cabdff1aSopenharmony_ci case AV_CODEC_ID_AVS2: 201cabdff1aSopenharmony_ci case AV_CODEC_ID_AVS3: 202cabdff1aSopenharmony_ci case AV_CODEC_ID_CAVS: 203cabdff1aSopenharmony_ci case AV_CODEC_ID_MPEG4: 204cabdff1aSopenharmony_ci i = mpeg4video_split(pkt->data, pkt->size); 205cabdff1aSopenharmony_ci break; 206cabdff1aSopenharmony_ci case AV_CODEC_ID_H264: 207cabdff1aSopenharmony_ci i = h264_split(pkt->data, pkt->size); 208cabdff1aSopenharmony_ci break; 209cabdff1aSopenharmony_ci case AV_CODEC_ID_HEVC: 210cabdff1aSopenharmony_ci i = hevc_split(pkt->data, pkt->size); 211cabdff1aSopenharmony_ci break; 212cabdff1aSopenharmony_ci case AV_CODEC_ID_MPEG1VIDEO: 213cabdff1aSopenharmony_ci case AV_CODEC_ID_MPEG2VIDEO: 214cabdff1aSopenharmony_ci i = mpegvideo_split(pkt->data, pkt->size); 215cabdff1aSopenharmony_ci break; 216cabdff1aSopenharmony_ci case AV_CODEC_ID_VC1: 217cabdff1aSopenharmony_ci i = vc1_split(pkt->data, pkt->size); 218cabdff1aSopenharmony_ci break; 219cabdff1aSopenharmony_ci default: 220cabdff1aSopenharmony_ci i = 0; 221cabdff1aSopenharmony_ci } 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ci pkt->data += i; 224cabdff1aSopenharmony_ci pkt->size -= i; 225cabdff1aSopenharmony_ci } 226cabdff1aSopenharmony_ci 227cabdff1aSopenharmony_ci return 0; 228cabdff1aSopenharmony_ci} 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(RemoveExtradataContext, x) 231cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) 232cabdff1aSopenharmony_cistatic const AVOption options[] = { 233cabdff1aSopenharmony_ci { "freq", NULL, OFFSET(freq), AV_OPT_TYPE_INT, { .i64 = REMOVE_FREQ_KEYFRAME }, REMOVE_FREQ_KEYFRAME, REMOVE_FREQ_NONKEYFRAME, FLAGS, "freq" }, 234cabdff1aSopenharmony_ci { "k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_NONKEYFRAME }, .flags = FLAGS, .unit = "freq" }, 235cabdff1aSopenharmony_ci { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_KEYFRAME }, .flags = FLAGS, .unit = "freq" }, 236cabdff1aSopenharmony_ci { "e", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL }, .flags = FLAGS, .unit = "freq" }, 237cabdff1aSopenharmony_ci { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL }, .flags = FLAGS, .unit = "freq" }, 238cabdff1aSopenharmony_ci { NULL }, 239cabdff1aSopenharmony_ci}; 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_cistatic const AVClass remove_extradata_class = { 242cabdff1aSopenharmony_ci .class_name = "remove_extradata", 243cabdff1aSopenharmony_ci .item_name = av_default_item_name, 244cabdff1aSopenharmony_ci .option = options, 245cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 246cabdff1aSopenharmony_ci}; 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_remove_extradata_bsf = { 249cabdff1aSopenharmony_ci .p.name = "remove_extra", 250cabdff1aSopenharmony_ci .p.priv_class = &remove_extradata_class, 251cabdff1aSopenharmony_ci .priv_data_size = sizeof(RemoveExtradataContext), 252cabdff1aSopenharmony_ci .filter = remove_extradata, 253cabdff1aSopenharmony_ci}; 254