aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorJames Almer <jamrial@gmail.com>2023-03-19 11:32:38 -0300
committerJames Almer <jamrial@gmail.com>2023-04-08 10:28:41 -0300
commitbda44f0f39e8ee646e54f15989d7845f4bf58d26 (patch)
tree41a4aa5edca209d4b7b05ec2c3e5a720192caf7f /libavformat
parente1f691b2e82c38d3c87a22a0e58f8a3e41c67428 (diff)
downloadffmpeg-bda44f0f39e8ee646e54f15989d7845f4bf58d26.tar.gz
avformat/matroskaenc: support writing Dynamic HDR10+ packet side data
Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/matroskaenc.c79
1 files changed, 66 insertions, 13 deletions
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 3b0998ecc8..59ed5be951 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -44,6 +44,7 @@
#include "libavutil/channel_layout.h"
#include "libavutil/crc.h"
#include "libavutil/dict.h"
+#include "libavutil/hdr_dynamic_metadata.h"
#include "libavutil/intfloat.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/lfg.h"
@@ -59,6 +60,7 @@
#include "libavcodec/av1.h"
#include "libavcodec/avcodec.h"
+#include "libavcodec/bytestream.h"
#include "libavcodec/codec_desc.h"
#include "libavcodec/xiph.h"
#include "libavcodec/mpeg4audio.h"
@@ -1612,6 +1614,10 @@ static void mkv_write_blockadditionmapping(AVFormatContext *s, MatroskaMuxContex
// we either write the default value here, or a void element. Either of them will
// be overwritten when finishing the track.
put_ebml_uint(mkv->track.bc, MATROSKA_ID_TRACKMAXBLKADDID, 0);
+ // Similarly, reserve space for an eventual HDR10+ ITU T.35 metadata BlockAdditionMapping.
+ put_ebml_void(pb, 3 /* BlockAdditionMapping */
+ + 4 /* BlockAddIDValue */
+ + 4 /* BlockAddIDType */);
}
if (dovi && dovi->dv_profile <= 10) {
@@ -2618,17 +2624,27 @@ static int webm_reformat_vtt(MatroskaMuxContext *mkv, AVIOContext *pb,
return 0;
}
+static void mkv_write_blockadditional(EbmlWriter *writer, const uint8_t *buf,
+ size_t size, uint64_t additional_id)
+{
+ ebml_writer_open_master(writer, MATROSKA_ID_BLOCKMORE);
+ ebml_writer_add_uint(writer, MATROSKA_ID_BLOCKADDID, additional_id);
+ ebml_writer_add_bin (writer, MATROSKA_ID_BLOCKADDITIONAL, buf, size);
+ ebml_writer_close_master(writer);
+}
+
static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv,
AVIOContext *pb, const AVCodecParameters *par,
mkv_track *track, const AVPacket *pkt,
int keyframe, int64_t ts, uint64_t duration,
int force_blockgroup, int64_t relative_packet_pos)
{
- uint8_t *side_data;
+ uint8_t *side_data, *buf = NULL;
size_t side_data_size;
uint64_t additional_id;
unsigned track_number = track->track_num;
- EBML_WRITER(9);
+ int ret;
+ EBML_WRITER(13);
mkv->cur_block.track = track;
mkv->cur_block.pkt = pkt;
@@ -2663,24 +2679,52 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv,
}
}
+ ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS);
side_data = av_packet_get_side_data(pkt,
AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
&side_data_size);
if (side_data && side_data_size >= 8 &&
// Only the Codec-specific BlockMore (id == 1) is currently supported.
(additional_id = AV_RB64(side_data)) == MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE) {
- ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS);
- ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKMORE);
- /* Until dbc50f8a our demuxer used a wrong default value
- * of BlockAddID, so we write it unconditionally. */
- ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKADDID, additional_id);
- ebml_writer_add_bin (&writer, MATROSKA_ID_BLOCKADDITIONAL,
- side_data + 8, side_data_size - 8);
- ebml_writer_close_master(&writer);
- ebml_writer_close_master(&writer);
- track->max_blockaddid = additional_id;
+ mkv_write_blockadditional(&writer, side_data + 8, side_data_size - 8,
+ additional_id);
+ track->max_blockaddid = FFMAX(track->max_blockaddid, additional_id);
+ }
+
+ side_data = av_packet_get_side_data(pkt,
+ AV_PKT_DATA_DYNAMIC_HDR10_PLUS,
+ &side_data_size);
+ if (side_data && side_data_size) {
+ uint8_t *payload;
+ size_t payload_size, buf_size;
+ int ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, NULL,
+ &payload_size);
+ if (ret < 0)
+ return ret;
+
+ buf_size = payload_size + 6;
+ buf = payload = av_malloc(buf_size);
+ if (!buf)
+ return AVERROR(ENOMEM);
+
+ bytestream_put_byte(&payload, 0xB5); // country_code
+ bytestream_put_be16(&payload, 0x3C); // provider_code
+ bytestream_put_be16(&payload, 0x01); // provider_oriented_code
+ bytestream_put_byte(&payload, 0x04); // application_identifier
+
+ ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, &payload,
+ &payload_size);
+ if (ret < 0)
+ return ret;
+
+ mkv_write_blockadditional(&writer, buf, buf_size,
+ MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
+ track->max_blockaddid = FFMAX(track->max_blockaddid,
+ MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
}
+ ebml_writer_close_or_discard_master(&writer);
+
if (!force_blockgroup && writer.nb_elements == 2) {
/* Nothing except the BlockGroup + Block. Can use a SimpleBlock. */
writer.elements++; // Skip the BlockGroup.
@@ -2693,7 +2737,10 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv,
ebml_writer_add_sint(&writer, MATROSKA_ID_BLOCKREFERENCE,
track->last_timestamp - ts);
- return ebml_writer_write(&writer, pb);
+ ret = ebml_writer_write(&writer, pb);
+ av_free(buf);
+
+ return ret;
}
static int mkv_end_cluster(AVFormatContext *s)
@@ -3095,6 +3142,12 @@ after_cues:
avio_seek(mkv->track.bc, track->blockadditionmapping_offset, SEEK_SET);
put_ebml_uint(mkv->track.bc, MATROSKA_ID_TRACKMAXBLKADDID, track->max_blockaddid);
+ if (track->max_blockaddid == MATROSKA_BLOCK_ADD_ID_ITU_T_T35) {
+ ebml_master mapping_master = start_ebml_master(mkv->track.bc, MATROSKA_ID_TRACKBLKADDMAPPING, 8);
+ put_ebml_uint(mkv->track.bc, MATROSKA_ID_BLKADDIDTYPE, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35);
+ put_ebml_uint(mkv->track.bc, MATROSKA_ID_BLKADDIDVALUE, MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
+ end_ebml_master(mkv->track.bc, mapping_master);
+ }
}
avio_seek(pb, mkv->track.pos, SEEK_SET);