1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Prores Metadata bitstream filter 3cabdff1aSopenharmony_ci * Copyright (c) 2018 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 * Prores Metadata bitstream filter 25cabdff1aSopenharmony_ci * set frame colorspace property 26cabdff1aSopenharmony_ci */ 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include "libavutil/common.h" 29cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 30cabdff1aSopenharmony_ci#include "libavutil/opt.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci#include "bsf.h" 33cabdff1aSopenharmony_ci#include "bsf_internal.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_citypedef struct ProresMetadataContext { 36cabdff1aSopenharmony_ci const AVClass *class; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci int color_primaries; 39cabdff1aSopenharmony_ci int transfer_characteristics; 40cabdff1aSopenharmony_ci int matrix_coefficients; 41cabdff1aSopenharmony_ci} ProresMetadataContext; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_cistatic int prores_metadata(AVBSFContext *bsf, AVPacket *pkt) 44cabdff1aSopenharmony_ci{ 45cabdff1aSopenharmony_ci ProresMetadataContext *ctx = bsf->priv_data; 46cabdff1aSopenharmony_ci int ret = 0; 47cabdff1aSopenharmony_ci int buf_size; 48cabdff1aSopenharmony_ci uint8_t *buf; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci ret = ff_bsf_get_packet_ref(bsf, pkt); 51cabdff1aSopenharmony_ci if (ret < 0) 52cabdff1aSopenharmony_ci return ret; 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_ci ret = av_packet_make_writable(pkt); 55cabdff1aSopenharmony_ci if (ret < 0) 56cabdff1aSopenharmony_ci goto fail; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci buf = pkt->data; 59cabdff1aSopenharmony_ci buf_size = pkt->size; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci /* check start of the prores frame */ 62cabdff1aSopenharmony_ci if (buf_size < 28) { 63cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "not enough data in prores frame\n"); 64cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 65cabdff1aSopenharmony_ci goto fail; 66cabdff1aSopenharmony_ci } 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci if (AV_RL32(buf + 4) != AV_RL32("icpf")) { 69cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "invalid frame header\n"); 70cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 71cabdff1aSopenharmony_ci goto fail; 72cabdff1aSopenharmony_ci } 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci if (AV_RB16(buf + 8) < 28) { 75cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "invalid frame header size\n"); 76cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 77cabdff1aSopenharmony_ci goto fail; 78cabdff1aSopenharmony_ci } 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci /* set the new values */ 81cabdff1aSopenharmony_ci if (ctx->color_primaries != -1) 82cabdff1aSopenharmony_ci buf[8+14] = ctx->color_primaries; 83cabdff1aSopenharmony_ci if (ctx->transfer_characteristics != -1) 84cabdff1aSopenharmony_ci buf[8+15] = ctx->transfer_characteristics; 85cabdff1aSopenharmony_ci if (ctx->matrix_coefficients != -1) 86cabdff1aSopenharmony_ci buf[8+16] = ctx->matrix_coefficients; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_cifail: 89cabdff1aSopenharmony_ci if (ret < 0) 90cabdff1aSopenharmony_ci av_packet_unref(pkt); 91cabdff1aSopenharmony_ci return ret; 92cabdff1aSopenharmony_ci} 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_cistatic const enum AVCodecID codec_ids[] = { 95cabdff1aSopenharmony_ci AV_CODEC_ID_PRORES, AV_CODEC_ID_NONE, 96cabdff1aSopenharmony_ci}; 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_cistatic int prores_metadata_init(AVBSFContext *bsf) 99cabdff1aSopenharmony_ci{ 100cabdff1aSopenharmony_ci ProresMetadataContext *ctx = bsf->priv_data; 101cabdff1aSopenharmony_ci /*! check options */ 102cabdff1aSopenharmony_ci switch (ctx->color_primaries) { 103cabdff1aSopenharmony_ci case -1: 104cabdff1aSopenharmony_ci case 0: 105cabdff1aSopenharmony_ci case AVCOL_PRI_BT709: 106cabdff1aSopenharmony_ci case AVCOL_PRI_BT470BG: 107cabdff1aSopenharmony_ci case AVCOL_PRI_SMPTE170M: 108cabdff1aSopenharmony_ci case AVCOL_PRI_BT2020: 109cabdff1aSopenharmony_ci case AVCOL_PRI_SMPTE431: 110cabdff1aSopenharmony_ci case AVCOL_PRI_SMPTE432: 111cabdff1aSopenharmony_ci break; 112cabdff1aSopenharmony_ci default: 113cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "Color primaries %d is not a valid value\n", ctx->color_primaries); 114cabdff1aSopenharmony_ci return AVERROR(EINVAL); 115cabdff1aSopenharmony_ci } 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_ci switch (ctx->matrix_coefficients) { 118cabdff1aSopenharmony_ci case -1: 119cabdff1aSopenharmony_ci case 0: 120cabdff1aSopenharmony_ci case AVCOL_SPC_BT709: 121cabdff1aSopenharmony_ci case AVCOL_SPC_SMPTE170M: 122cabdff1aSopenharmony_ci case AVCOL_SPC_BT2020_NCL: 123cabdff1aSopenharmony_ci break; 124cabdff1aSopenharmony_ci default: 125cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "Colorspace %d is not a valid value\n", ctx->matrix_coefficients); 126cabdff1aSopenharmony_ci return AVERROR(EINVAL); 127cabdff1aSopenharmony_ci } 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci return 0; 130cabdff1aSopenharmony_ci} 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(ProresMetadataContext, x) 133cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_BSF_PARAM) 134cabdff1aSopenharmony_cistatic const AVOption options[] = { 135cabdff1aSopenharmony_ci {"color_primaries", "select color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_PRI_SMPTE432, FLAGS, "color_primaries"}, 136cabdff1aSopenharmony_ci {"auto", "keep the same color primaries", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, 137cabdff1aSopenharmony_ci {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, 138cabdff1aSopenharmony_ci {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, 139cabdff1aSopenharmony_ci {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470BG}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, 140cabdff1aSopenharmony_ci {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE170M}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, 141cabdff1aSopenharmony_ci {"bt2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT2020}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, 142cabdff1aSopenharmony_ci {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, 143cabdff1aSopenharmony_ci {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci {"color_trc", "select color transfer", OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_NB - 1, FLAGS, "color_trc"}, 146cabdff1aSopenharmony_ci {"auto", "keep the same color transfer", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, 147cabdff1aSopenharmony_ci {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, 148cabdff1aSopenharmony_ci {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, 149cabdff1aSopenharmony_ci {"smpte2084", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, 150cabdff1aSopenharmony_ci {"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci {"colorspace", "select colorspace", OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_SPC_BT2020_NCL, FLAGS, "colorspace"}, 153cabdff1aSopenharmony_ci {"auto", "keep the same colorspace", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, FLAGS, "colorspace"}, 154cabdff1aSopenharmony_ci {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, INT_MIN, INT_MAX, FLAGS, "colorspace"}, 155cabdff1aSopenharmony_ci {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT709}, INT_MIN, INT_MAX, FLAGS, "colorspace"}, 156cabdff1aSopenharmony_ci {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE170M}, INT_MIN, INT_MAX, FLAGS, "colorspace"}, 157cabdff1aSopenharmony_ci {"bt2020nc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_NCL}, INT_MIN, INT_MAX, FLAGS, "colorspace"}, 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ci { NULL }, 160cabdff1aSopenharmony_ci}; 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_cistatic const AVClass prores_metadata_class = { 163cabdff1aSopenharmony_ci .class_name = "prores_metadata_bsf", 164cabdff1aSopenharmony_ci .item_name = av_default_item_name, 165cabdff1aSopenharmony_ci .option = options, 166cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 167cabdff1aSopenharmony_ci}; 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_prores_metadata_bsf = { 170cabdff1aSopenharmony_ci .p.name = "prores_metadata", 171cabdff1aSopenharmony_ci .p.codec_ids = codec_ids, 172cabdff1aSopenharmony_ci .p.priv_class = &prores_metadata_class, 173cabdff1aSopenharmony_ci .priv_data_size = sizeof(ProresMetadataContext), 174cabdff1aSopenharmony_ci .init = prores_metadata_init, 175cabdff1aSopenharmony_ci .filter = prores_metadata, 176cabdff1aSopenharmony_ci}; 177