1/* 2 * HAPQA extract bitstream filter 3 * Copyright (c) 2017 Jokyo Images 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * HAPQA extract bitstream filter 25 * extract one of the two textures of the HAQA 26 */ 27 28#include "bsf.h" 29#include "bsf_internal.h" 30#include "bytestream.h" 31#include "hap.h" 32 33typedef struct HapqaExtractContext { 34 const AVClass *class; 35 int texture;/* index of the texture to keep (0 for rgb or 1 for alpha) */ 36} HapqaExtractContext; 37 38static int check_texture(HapqaExtractContext *ctx, int section_type) { 39 if (((ctx->texture == 0)&&((section_type & 0x0F) == 0x0F)) || /* HapQ texture and rgb extract */ 40 ((ctx->texture == 1)&&((section_type & 0x0F) == 0x01))) /* HapAlphaOnly texture and alpha extract */ 41 { 42 return 1; /* the texture is the one to keep */ 43 } else { 44 return 0; 45 } 46} 47 48static int hapqa_extract(AVBSFContext *bsf, AVPacket *pkt) 49{ 50 HapqaExtractContext *ctx = bsf->priv_data; 51 GetByteContext gbc; 52 int section_size; 53 enum HapSectionType section_type; 54 int start_section_size; 55 int target_packet_size = 0; 56 int ret = 0; 57 58 ret = ff_bsf_get_packet_ref(bsf, pkt); 59 if (ret < 0) 60 return ret; 61 62 bytestream2_init(&gbc, pkt->data, pkt->size); 63 ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); 64 if (ret != 0) 65 goto fail; 66 67 if ((section_type & 0x0F) != 0x0D) { 68 av_log(bsf, AV_LOG_ERROR, "Invalid section type for HAPQA %#04x.\n", section_type & 0x0F); 69 ret = AVERROR_INVALIDDATA; 70 goto fail; 71 } 72 73 start_section_size = 4; 74 75 bytestream2_seek(&gbc, start_section_size, SEEK_SET);/* go to start of the first texture */ 76 77 ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); 78 if (ret != 0) 79 goto fail; 80 81 target_packet_size = section_size + 4; 82 83 if (check_texture(ctx, section_type) == 0) { /* the texture is not the one to keep */ 84 start_section_size += 4 + section_size; 85 bytestream2_seek(&gbc, start_section_size, SEEK_SET);/* go to start of the second texture */ 86 ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); 87 if (ret != 0) 88 goto fail; 89 90 target_packet_size = section_size + 4; 91 92 if (check_texture(ctx, section_type) == 0){ /* the second texture is not the one to keep */ 93 av_log(bsf, AV_LOG_ERROR, "No valid texture found.\n"); 94 ret = AVERROR_INVALIDDATA; 95 goto fail; 96 } 97 } 98 99 pkt->data += start_section_size; 100 pkt->size = target_packet_size; 101 102fail: 103 if (ret < 0) 104 av_packet_unref(pkt); 105 return ret; 106} 107 108static const enum AVCodecID codec_ids[] = { 109 AV_CODEC_ID_HAP, AV_CODEC_ID_NONE, 110}; 111 112#define OFFSET(x) offsetof(HapqaExtractContext, x) 113#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_BSF_PARAM) 114static const AVOption options[] = { 115 { "texture", "texture to keep", OFFSET(texture), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "texture" }, 116 { "color", "keep HapQ texture", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "texture" }, 117 { "alpha", "keep HapAlphaOnly texture", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "texture" }, 118 { NULL }, 119}; 120 121static const AVClass hapqa_extract_class = { 122 .class_name = "hapqa_extract_bsf", 123 .item_name = av_default_item_name, 124 .option = options, 125 .version = LIBAVUTIL_VERSION_INT, 126}; 127 128const FFBitStreamFilter ff_hapqa_extract_bsf = { 129 .p.name = "hapqa_extract", 130 .p.codec_ids = codec_ids, 131 .p.priv_class = &hapqa_extract_class, 132 .priv_data_size = sizeof(HapqaExtractContext), 133 .filter = hapqa_extract, 134}; 135