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