1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * HAPQA extract bitstream filter 3cabdff1aSopenharmony_ci * Copyright (c) 2017 Jokyo Images 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/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * HAPQA extract bitstream filter 25cabdff1aSopenharmony_ci * extract one of the two textures of the HAQA 26cabdff1aSopenharmony_ci */ 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include "bsf.h" 29cabdff1aSopenharmony_ci#include "bsf_internal.h" 30cabdff1aSopenharmony_ci#include "bytestream.h" 31cabdff1aSopenharmony_ci#include "hap.h" 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_citypedef struct HapqaExtractContext { 34cabdff1aSopenharmony_ci const AVClass *class; 35cabdff1aSopenharmony_ci int texture;/* index of the texture to keep (0 for rgb or 1 for alpha) */ 36cabdff1aSopenharmony_ci} HapqaExtractContext; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_cistatic int check_texture(HapqaExtractContext *ctx, int section_type) { 39cabdff1aSopenharmony_ci if (((ctx->texture == 0)&&((section_type & 0x0F) == 0x0F)) || /* HapQ texture and rgb extract */ 40cabdff1aSopenharmony_ci ((ctx->texture == 1)&&((section_type & 0x0F) == 0x01))) /* HapAlphaOnly texture and alpha extract */ 41cabdff1aSopenharmony_ci { 42cabdff1aSopenharmony_ci return 1; /* the texture is the one to keep */ 43cabdff1aSopenharmony_ci } else { 44cabdff1aSopenharmony_ci return 0; 45cabdff1aSopenharmony_ci } 46cabdff1aSopenharmony_ci} 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_cistatic int hapqa_extract(AVBSFContext *bsf, AVPacket *pkt) 49cabdff1aSopenharmony_ci{ 50cabdff1aSopenharmony_ci HapqaExtractContext *ctx = bsf->priv_data; 51cabdff1aSopenharmony_ci GetByteContext gbc; 52cabdff1aSopenharmony_ci int section_size; 53cabdff1aSopenharmony_ci enum HapSectionType section_type; 54cabdff1aSopenharmony_ci int start_section_size; 55cabdff1aSopenharmony_ci int target_packet_size = 0; 56cabdff1aSopenharmony_ci int ret = 0; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci ret = ff_bsf_get_packet_ref(bsf, pkt); 59cabdff1aSopenharmony_ci if (ret < 0) 60cabdff1aSopenharmony_ci return ret; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci bytestream2_init(&gbc, pkt->data, pkt->size); 63cabdff1aSopenharmony_ci ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); 64cabdff1aSopenharmony_ci if (ret != 0) 65cabdff1aSopenharmony_ci goto fail; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci if ((section_type & 0x0F) != 0x0D) { 68cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "Invalid section type for HAPQA %#04x.\n", section_type & 0x0F); 69cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 70cabdff1aSopenharmony_ci goto fail; 71cabdff1aSopenharmony_ci } 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci start_section_size = 4; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci bytestream2_seek(&gbc, start_section_size, SEEK_SET);/* go to start of the first texture */ 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); 78cabdff1aSopenharmony_ci if (ret != 0) 79cabdff1aSopenharmony_ci goto fail; 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_ci target_packet_size = section_size + 4; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci if (check_texture(ctx, section_type) == 0) { /* the texture is not the one to keep */ 84cabdff1aSopenharmony_ci start_section_size += 4 + section_size; 85cabdff1aSopenharmony_ci bytestream2_seek(&gbc, start_section_size, SEEK_SET);/* go to start of the second texture */ 86cabdff1aSopenharmony_ci ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); 87cabdff1aSopenharmony_ci if (ret != 0) 88cabdff1aSopenharmony_ci goto fail; 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci target_packet_size = section_size + 4; 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci if (check_texture(ctx, section_type) == 0){ /* the second texture is not the one to keep */ 93cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "No valid texture found.\n"); 94cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 95cabdff1aSopenharmony_ci goto fail; 96cabdff1aSopenharmony_ci } 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci pkt->data += start_section_size; 100cabdff1aSopenharmony_ci pkt->size = target_packet_size; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_cifail: 103cabdff1aSopenharmony_ci if (ret < 0) 104cabdff1aSopenharmony_ci av_packet_unref(pkt); 105cabdff1aSopenharmony_ci return ret; 106cabdff1aSopenharmony_ci} 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_cistatic const enum AVCodecID codec_ids[] = { 109cabdff1aSopenharmony_ci AV_CODEC_ID_HAP, AV_CODEC_ID_NONE, 110cabdff1aSopenharmony_ci}; 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(HapqaExtractContext, x) 113cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_BSF_PARAM) 114cabdff1aSopenharmony_cistatic const AVOption options[] = { 115cabdff1aSopenharmony_ci { "texture", "texture to keep", OFFSET(texture), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "texture" }, 116cabdff1aSopenharmony_ci { "color", "keep HapQ texture", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "texture" }, 117cabdff1aSopenharmony_ci { "alpha", "keep HapAlphaOnly texture", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "texture" }, 118cabdff1aSopenharmony_ci { NULL }, 119cabdff1aSopenharmony_ci}; 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_cistatic const AVClass hapqa_extract_class = { 122cabdff1aSopenharmony_ci .class_name = "hapqa_extract_bsf", 123cabdff1aSopenharmony_ci .item_name = av_default_item_name, 124cabdff1aSopenharmony_ci .option = options, 125cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 126cabdff1aSopenharmony_ci}; 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_hapqa_extract_bsf = { 129cabdff1aSopenharmony_ci .p.name = "hapqa_extract", 130cabdff1aSopenharmony_ci .p.codec_ids = codec_ids, 131cabdff1aSopenharmony_ci .p.priv_class = &hapqa_extract_class, 132cabdff1aSopenharmony_ci .priv_data_size = sizeof(HapqaExtractContext), 133cabdff1aSopenharmony_ci .filter = hapqa_extract, 134cabdff1aSopenharmony_ci}; 135