diff options
Diffstat (limited to 'demux')
-rw-r--r-- | demux/cache.c | 1 | ||||
-rw-r--r-- | demux/demux.c | 87 | ||||
-rw-r--r-- | demux/demux.h | 11 | ||||
-rw-r--r-- | demux/demux_cue.c | 1 | ||||
-rw-r--r-- | demux/demux_edl.c | 2 | ||||
-rw-r--r-- | demux/demux_lavf.c | 20 | ||||
-rw-r--r-- | demux/demux_mf.c | 2 | ||||
-rw-r--r-- | demux/demux_mkv.c | 175 | ||||
-rw-r--r-- | demux/demux_mkv_timeline.c | 3 | ||||
-rw-r--r-- | demux/demux_playlist.c | 2 | ||||
-rw-r--r-- | demux/demux_raw.c | 1 | ||||
-rw-r--r-- | demux/ebml.h | 3 | ||||
-rw-r--r-- | demux/packet.c | 56 | ||||
-rw-r--r-- | demux/stheader.h | 16 |
14 files changed, 309 insertions, 71 deletions
diff --git a/demux/cache.c b/demux/cache.c index 6398f61823..036ed35d2d 100644 --- a/demux/cache.c +++ b/demux/cache.c @@ -20,7 +20,6 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> -#include <unistd.h> #include "cache.h" #include "common/msg.h" diff --git a/demux/demux.c b/demux/demux.c index 386b088148..6feb97e998 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -26,7 +26,6 @@ #include <string.h> #include <sys/stat.h> #include <sys/types.h> -#include <unistd.h> #include "cache.h" #include "config.h" @@ -663,7 +662,7 @@ static void update_seek_ranges(struct demux_cached_range *range) } } - if (range->seek_start >= range->seek_end) + if (range->seek_start >= range->seek_end && !(range->is_bof && range->is_eof)) goto broken; prune_metadata(range); @@ -3173,19 +3172,26 @@ void demux_update(demuxer_t *demuxer, double pts) static void demux_init_cuesheet(struct demuxer *demuxer) { + if (demuxer->num_chapters) + return; + + struct sh_stream *sh = demuxer->in->metadata_stream; char *cue = mp_tags_get_str(demuxer->metadata, "cuesheet"); - if (cue && !demuxer->num_chapters) { - struct cue_file *f = mp_parse_cue(bstr0(cue)); - if (f) { - if (mp_check_embedded_cue(f) < 0) { - MP_WARN(demuxer, "Embedded cue sheet references more than one file. " - "Ignoring it.\n"); - } else { - for (int n = 0; n < f->num_tracks; n++) { - struct cue_track *t = &f->tracks[n]; - int idx = demuxer_add_chapter(demuxer, "", t->start, -1); - mp_tags_merge(demuxer->chapters[idx].metadata, t->tags); - } + if (!cue && sh) + cue = mp_tags_get_str(sh->tags, "cuesheet"); + if (!cue) + return; + + struct cue_file *f = mp_parse_cue(bstr0(cue)); + if (f) { + if (mp_check_embedded_cue(f) < 0) { + MP_WARN(demuxer, "Embedded cue sheet references more than one file. " + "Ignoring it.\n"); + } else { + for (int n = 0; n < f->num_tracks; n++) { + struct cue_track *t = &f->tracks[n]; + int idx = demuxer_add_chapter(demuxer, "", t->start, -1); + mp_tags_merge(demuxer->chapters[idx].metadata, t->tags); } } talloc_free(f); @@ -4480,9 +4486,11 @@ void demux_get_reader_state(struct demuxer *demuxer, struct demux_reader_state * *r = (struct demux_reader_state){ .eof = in->eof, - .ts_reader = MP_NOPTS_VALUE, - .ts_end = MP_NOPTS_VALUE, - .ts_duration = -1, + .ts_info = { + .reader = MP_NOPTS_VALUE, + .end = MP_NOPTS_VALUE, + .duration = -1, + }, .total_bytes = in->total_bytes, .seeking = in->seeking_in_progress, .low_level_seeks = in->low_level_seeks, @@ -4492,24 +4500,55 @@ void demux_get_reader_state(struct demuxer *demuxer, struct demux_reader_state * .file_cache_bytes = in->cache ? demux_cache_get_size(in->cache) : -1, }; bool any_packets = false; + for (int n = 0; n < STREAM_TYPE_COUNT; n++) { + r->ts_per_stream[n] = r->ts_info; + } for (int n = 0; n < in->num_streams; n++) { struct demux_stream *ds = in->streams[n]->ds; if (ds->eager && !(!ds->queue->head && ds->eof) && !ds->ignore_eof) { r->underrun |= !ds->reader_head && !ds->eof && !ds->still_image; - r->ts_reader = MP_PTS_MAX(r->ts_reader, ds->base_ts); - r->ts_end = MP_PTS_MAX(r->ts_end, ds->queue->last_ts); any_packets |= !!ds->reader_head; + + double ts_reader = ds->base_ts; + double ts_end = ds->queue->last_ts; + double ts_duration = -1; + if (ts_reader != MP_NOPTS_VALUE && ts_reader <= ts_end) + ts_duration = ts_end - ts_reader; + + struct demux_ctrl_ts_info *i = &r->ts_per_stream[ds->type]; + i->reader = MP_PTS_MIN(i->reader, ts_reader); + i->end = MP_PTS_MIN(i->end, ts_end); + i->duration = ts_duration; } r->fw_bytes += get_forward_buffered_bytes(ds); } + struct demux_ctrl_ts_info *ots = &r->ts_info; + // find stream type with lowest duration and use its state + for (int n = 0; n < STREAM_TYPE_COUNT; n++) { + struct demux_ctrl_ts_info *ts = &r->ts_per_stream[n]; + if (r->ts_info.duration != -1) { + // skip if timestamps unknown + if (ts->duration == -1) + continue; + // skip if we already know of a smaller cached stream + if (ts->duration > ots->duration) + continue; + // skip empty subtitle streams when other streams exist + if (n == STREAM_SUB && ts->duration == 0.0) + continue; + } + ots->duration = ts->duration; + ots->reader = ts->reader; + ots->end = ts->end; + } r->idle = (!in->reading && !r->underrun) || r->eof; r->underrun &= !r->idle && in->threading; - r->ts_reader = MP_ADD_PTS(r->ts_reader, in->ts_offset); - r->ts_end = MP_ADD_PTS(r->ts_end, in->ts_offset); - if (r->ts_reader != MP_NOPTS_VALUE && r->ts_reader <= r->ts_end) - r->ts_duration = r->ts_end - r->ts_reader; + ots->reader = MP_ADD_PTS(ots->reader, in->ts_offset); + ots->end = MP_ADD_PTS(ots->end, in->ts_offset); + if (ots->reader != MP_NOPTS_VALUE && ots->reader <= ots->end) + ots->duration = ots->end - ots->reader; if (in->seeking || !any_packets) - r->ts_duration = 0; + ots->duration = 0; for (int n = 0; n < MPMIN(in->num_ranges, MAX_SEEK_RANGES); n++) { struct demux_cached_range *range = in->ranges[n]; if (range->seek_start != MP_NOPTS_VALUE) { diff --git a/demux/demux.h b/demux/demux.h index 08904f26cc..401f1d146c 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -36,12 +36,17 @@ struct demux_seek_range { double start, end; }; +struct demux_ctrl_ts_info { + double duration; + double reader; // approx. timestamp of decoder position + double end; // approx. timestamp of end of buffered range +}; + struct demux_reader_state { bool eof, underrun, idle; bool bof_cached, eof_cached; - double ts_duration; - double ts_reader; // approx. timerstamp of decoder position - double ts_end; // approx. timestamp of end of buffered range + struct demux_ctrl_ts_info ts_info; + struct demux_ctrl_ts_info ts_per_stream[STREAM_TYPE_COUNT]; int64_t total_bytes; int64_t fw_bytes; int64_t file_cache_bytes; diff --git a/demux/demux_cue.c b/demux/demux_cue.c index 4937ec967b..2549aed101 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -20,7 +20,6 @@ #include <stdlib.h> #include <stdbool.h> #include <string.h> -#include <dirent.h> #include <inttypes.h> #include "osdep/io.h" diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 356b7eefb5..55af553661 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -567,7 +567,7 @@ error: static void fix_filenames(struct tl_parts *parts, char *source_path) { - if (bstr_equals0(mp_split_proto(bstr0(source_path), NULL), "edl")) + if (!bstrcasecmp0(mp_split_proto(bstr0(source_path), NULL), "edl")) return; struct bstr dirname = mp_dirname(source_path); for (int n = 0; n < parts->num_parts; n++) { diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index fa9fd5cee8..c1dbe6a8a8 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -21,7 +21,6 @@ #include <limits.h> #include <stdbool.h> #include <string.h> -#include <strings.h> #include <errno.h> #include <assert.h> @@ -41,6 +40,7 @@ #include "audio/chmap_avchannel.h" +#include "common/common.h" #include "common/msg.h" #include "common/tags.h" #include "common/av_common.h" @@ -184,6 +184,7 @@ static const struct format_hack format_hacks[] = { // In theory, such streams might contain timestamps, but virtually none do. {"h264", .if_flags = AVFMT_NOTIMESTAMPS }, {"hevc", .if_flags = AVFMT_NOTIMESTAMPS }, + {"vvc", .if_flags = AVFMT_NOTIMESTAMPS }, // Some Ogg shoutcast streams are essentially concatenated OGG files. They // reset timestamps, which causes all sorts of problems. @@ -464,12 +465,18 @@ static int lavf_check_file(demuxer_t *demuxer, enum demux_check check) } } - // HLS streams seems to be not well tagged, so matching mime type is not - // enough. Strip URL parameters and match extension. - bstr ext = bstr_get_ext(bstr_split(bstr0(priv->filename), "?#", NULL)); + // HLS streams do not seem to be well tagged, so matching by MIME type is + // not enough - we need to strip the query string and match by their + // extensions. We also pass jpg filenames to fix issues like #13192 (jpgs + // being treated as videos due to a bogus second frame) and #13431 (jpgs + // misdetected as mpegts). We don't pass filenames otherwise to not + // misdetect files with a wrong extension, as described in 74e62ed2d1. + bstr ext = bstr_get_ext(mp_is_url(bstr0(priv->filename)) + ? bstr_split(bstr0(priv->filename), "?#", NULL) + : bstr0(priv->filename)); AVProbeData avpd = { - // Disable file-extension matching with normal checks, except for HLS .filename = !bstrcasecmp0(ext, "m3u8") || !bstrcasecmp0(ext, "m3u") || + !bstrcasecmp0(ext, "jpg") || !bstrcasecmp0(ext, "jpeg") || check <= DEMUX_CHECK_REQUEST ? priv->filename : "", .buf_size = 0, .buf = av_mallocz(PROBE_BUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE), @@ -789,6 +796,9 @@ static void handle_new_stream(demuxer_t *demuxer, int i) MP_VERBOSE(demuxer, "Found Dolby Vision config record: profile " "%d level %d\n", cfg->dv_profile, cfg->dv_level); av_format_inject_global_side_data(avfc); + sh->codec->dovi = true; + sh->codec->dv_profile = cfg->dv_profile; + sh->codec->dv_level = cfg->dv_level; } // This also applies to vfw-muxed mkv, but we can't detect these easily. diff --git a/demux/demux_mf.c b/demux/demux_mf.c index d971f04c96..d1e80a27a8 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -19,8 +19,6 @@ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <strings.h> -#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index bd823b7b39..4a9bfb2faf 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -29,6 +29,7 @@ #include <assert.h> #include <libavutil/common.h> +#include <libavutil/dovi_meta.h> #include <libavutil/lzo.h> #include <libavutil/intreadwrite.h> #include <libavutil/avstring.h> @@ -113,8 +114,9 @@ typedef struct mkv_track { struct pl_color_repr repr; struct pl_color_space color; uint32_t v_crop_top, v_crop_left, v_crop_right, v_crop_bottom; + float v_projection_pose_yaw; + float v_projection_pose_pitch; float v_projection_pose_roll; - bool v_projection_pose_roll_set; uint32_t a_channels, a_bps; float a_sfreq; @@ -153,6 +155,8 @@ typedef struct mkv_track { /* latest added index entry for this track */ size_t last_index_entry; + + AVDOVIDecoderConfigurationRecord *dovi_config; } mkv_track_t; typedef struct mkv_index { @@ -658,15 +662,30 @@ static void parse_trackcolour(struct demuxer *demuxer, struct mkv_track *track, static void parse_trackprojection(struct demuxer *demuxer, struct mkv_track *track, struct ebml_projection *projection) { - if (projection->n_projection_pose_yaw || projection->n_projection_pose_pitch) - MP_WARN(demuxer, "Projection pose yaw/pitch not supported!\n"); + if (projection->n_projection_pose_yaw) { + track->v_projection_pose_yaw = projection->projection_pose_yaw; + MP_DBG(demuxer, "| + Projection pose yaw: %f\n", + track->v_projection_pose_yaw); + } + + if (projection->n_projection_pose_pitch) { + track->v_projection_pose_pitch = projection->projection_pose_pitch; + MP_DBG(demuxer, "| + Projection pose pitch: %f\n", + track->v_projection_pose_pitch); + } if (projection->n_projection_pose_roll) { track->v_projection_pose_roll = projection->projection_pose_roll; - track->v_projection_pose_roll_set = true; MP_DBG(demuxer, "| + Projection pose roll: %f\n", track->v_projection_pose_roll); } + + if (track->v_projection_pose_yaw || track->v_projection_pose_pitch) { + MP_WARN(demuxer, "Not supported projection: yaw %f, pitch %f, roll %f\n", + track->v_projection_pose_yaw, + track->v_projection_pose_pitch, + track->v_projection_pose_roll); + } } static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track, @@ -730,6 +749,84 @@ static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track, parse_trackprojection(demuxer, track, &video->projection); } +static void parse_dovi_config(struct demuxer *demuxer, struct mkv_track *track, + const uint8_t *buf_ptr, size_t size) +{ + if (size < 4) + return; + + av_free(track->dovi_config); + + size_t dovi_size; + track->dovi_config = av_dovi_alloc(&dovi_size); + MP_HANDLE_OOM(track->dovi_config); + + track->dovi_config->dv_version_major = *buf_ptr++; // 8 bits + track->dovi_config->dv_version_minor = *buf_ptr++; // 8 bits + + uint32_t buf; + buf = *buf_ptr++ << 8; + buf |= *buf_ptr++; + + track->dovi_config->dv_profile = (buf >> 9) & 0x7f; // 7 bits + track->dovi_config->dv_level = (buf >> 3) & 0x3f; // 6 bits + track->dovi_config->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit + track->dovi_config->el_present_flag = (buf >> 1) & 0x01; // 1 bit + track->dovi_config->bl_present_flag = buf & 0x01; // 1 bit + + if (size >= 5) { + track->dovi_config->dv_bl_signal_compatibility_id = ((*buf_ptr++) >> 4) & 0x0f; // 4 bits + } else { + // 0 stands for None + // Dolby Vision V1.2.93 profiles and levels + track->dovi_config->dv_bl_signal_compatibility_id = 0; + } + + MP_DBG(demuxer, "| + Dolby Vision - version: %d.%d, profile: %d, level: %d, " + "RPU: %d, EL: %d, BL: %d, ID: %d\n", + track->dovi_config->dv_version_major, + track->dovi_config->dv_version_minor, + track->dovi_config->dv_profile, + track->dovi_config->dv_level, + track->dovi_config->rpu_present_flag, + track->dovi_config->el_present_flag, + track->dovi_config->bl_present_flag, + track->dovi_config->dv_bl_signal_compatibility_id); +} + +static void parse_block_addition_mapping(struct demuxer *demuxer, + struct mkv_track *track, + struct ebml_block_addition_mapping *block_addition_mapping, + int count) +{ + for (int i = 0; i < count; ++i) { + if (!block_addition_mapping->n_block_add_id_type) + continue; + switch (block_addition_mapping->block_add_id_type) { + case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: + break; + case MKBETAG('a','v','c','E'): + case MKBETAG('h','v','c','E'): + MP_WARN(demuxer, "Dolby Vision enhancement-layer playback is not supported.\n"); + break; + case MKBETAG('d','v','c','C'): + case MKBETAG('d','v','v','C'): + if (block_addition_mapping->n_block_add_id_extra_data) { + bstr data = block_addition_mapping->block_add_id_extra_data; + parse_dovi_config(demuxer, track, data.start, data.len); + } + break; + case MKBETAG('m','v','c','C'): + MP_WARN(demuxer, "MVC configuration is not supported.\n"); + break; + default: + MP_WARN(demuxer, "Unsupported block addition type: %" PRIx64 "\n", + block_addition_mapping->block_add_id_type); + } + block_addition_mapping++; + } +} + /** * \brief free any data associated with given track * \param track track of which to free data @@ -737,6 +834,7 @@ static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track, static void demux_mkv_free_trackentry(mkv_track_t *track) { talloc_free(track->parser_tmp); + av_freep(&track->dovi_config); talloc_free(track); } @@ -804,7 +902,10 @@ static void parse_trackentry(struct demuxer *demuxer, MP_DBG(demuxer, "| + CodecPrivate, length %u\n", track->private_size); } - if (entry->language) { + if (entry->language_bcp47) { + track->language = talloc_strdup(track, entry->language_bcp47); + MP_DBG(demuxer, "| + LanguageBCP47: %s\n", track->language); + } else if (entry->language) { track->language = talloc_strdup(track, entry->language); MP_DBG(demuxer, "| + Language: %s\n", track->language); } else { @@ -840,6 +941,12 @@ static void parse_trackentry(struct demuxer *demuxer, if (entry->n_codec_delay) track->codec_delay = entry->codec_delay / 1e9; + if (entry->n_block_addition_mapping) { + parse_block_addition_mapping(demuxer, track, + entry->block_addition_mapping, + entry->n_block_addition_mapping); + } + mkv_d->tracks[mkv_d->num_tracks++] = track; } @@ -1091,8 +1198,8 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) } } - MP_DBG(demuxer, "Chapter %u from %02d:%02d:%02d.%03d " - "to %02d:%02d:%02d.%03d, %s\n", i, + MP_DBG(demuxer, "Chapter %u from %02d:%02d:%02d.%09d " + "to %02d:%02d:%02d.%09d, %s\n", i, (int) (chapter.start / 60 / 60 / 1000000000), (int) ((chapter.start / 60 / 1000000000) % 60), (int) ((chapter.start / 1000000000) % 60), @@ -1442,6 +1549,7 @@ static const char *const mkv_video_tags[][2] = { {"V_DIRAC", "dirac"}, {"V_PRORES", "prores"}, {"V_MPEGH/ISO/HEVC", "hevc"}, + {"V_MPEGI/ISO/VVC", "vvc"}, {"V_SNOW", "snow"}, {"V_AV1", "av1"}, {"V_PNG", "png"}, @@ -1507,15 +1615,14 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track) sh_v->codec_tag = track->colorspace; sh_v->codec = "rawvideo"; } else if (strcmp(track->codec_id, "V_QUICKTIME") == 0) { - uint32_t fourcc1 = 0, fourcc2 = 0; if (track->private_size >= 8) { - fourcc1 = AV_RL32(track->private_data + 0); - fourcc2 = AV_RL32(track->private_data + 4); - } - if (fourcc1 == MKTAG('S', 'V', 'Q', '3') || - fourcc2 == MKTAG('S', 'V', 'Q', '3')) - { - sh_v->codec = "svq3"; + sh_v->codec_tag = AV_RL32(track->private_data + 4); + mp_set_codec_from_tag(sh_v); + // Some non-compliant files have fourcc at offset 0. + if (!sh_v->codec) { + sh_v->codec_tag = AV_RL32(track->private_data); + mp_set_codec_from_tag(sh_v); + } extradata = track->private_data; extradata_size = track->private_size; } @@ -1575,11 +1682,17 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track) sh_v->stereo_mode = track->stereo_mode; sh_v->color = track->color; - if (track->v_projection_pose_roll_set) { - int rotate = lrintf(fmodf(fmodf(track->v_projection_pose_roll, 360) + 360, 360)); + if (track->v_projection_pose_roll) { + int rotate = lrintf(fmodf(fmodf(-1 * track->v_projection_pose_roll, 360) + 360, 360)); sh_v->rotate = rotate; } + if (track->dovi_config) { + sh_v->dovi = true; + sh_v->dv_level = track->dovi_config->dv_level; + sh_v->dv_profile = track->dovi_config->dv_profile; + } + done: demux_add_sh_stream(demuxer, sh); @@ -2025,14 +2138,14 @@ static void probe_if_image(demuxer_t *demuxer) int64_t timecode = -1; // Arbitrary restriction on packet reading. - for (int i = 0; i < 1000; i++) { - int ret = read_next_block_into_queue(demuxer); - if (ret == 1 && mkv_d->blocks[i].track == track) { - if (timecode != mkv_d->blocks[i].timecode) - ++video_blocks; - timecode = mkv_d->blocks[i].timecode; - } - // No need to read more + for (size_t block = 0; block < 100000; block++) { + if (block >= mkv_d->num_blocks && read_next_block_into_queue(demuxer) != 1) + break; + if (mkv_d->blocks[block].track != track) + continue; + if (timecode != mkv_d->blocks[block].timecode) + ++video_blocks; + timecode = mkv_d->blocks[block].timecode; if (video_blocks > 1) break; } @@ -2879,6 +2992,18 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) add->block_additional.start, add->block_additional.len); } } + if (track->dovi_config) { + size_t dovi_size; + AVDOVIDecoderConfigurationRecord *dovi = av_dovi_alloc(&dovi_size); + MP_HANDLE_OOM(dovi); + memcpy(dovi, track->dovi_config, dovi_size); + if (av_packet_add_side_data(dp->avpacket, + AV_PKT_DATA_DOVI_CONF, + (uint8_t *)dovi, dovi_size) < 0) + { + av_free(dovi); + } + } mkv_parse_and_add_packet(demuxer, track, dp); talloc_free_children(track->parser_tmp); diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 0c23e27d25..0190213b4e 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -19,12 +19,9 @@ #include <stdbool.h> #include <inttypes.h> #include <assert.h> -#include <dirent.h> #include <string.h> -#include <strings.h> #include <sys/types.h> #include <sys/stat.h> -#include <unistd.h> #include <libavutil/common.h> #include "osdep/io.h" diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c index 66be4b1270..28abfe09c2 100644 --- a/demux/demux_playlist.c +++ b/demux/demux_playlist.c @@ -17,8 +17,6 @@ #include <stdlib.h> #include <string.h> -#include <strings.h> -#include <dirent.h> #include <libavutil/common.h> diff --git a/demux/demux_raw.c b/demux/demux_raw.c index 86b0368300..acb0251847 100644 --- a/demux/demux_raw.c +++ b/demux/demux_raw.c @@ -17,7 +17,6 @@ #include <stdlib.h> #include <stdio.h> -#include <unistd.h> #include <string.h> #include <libavcodec/avcodec.h> diff --git a/demux/ebml.h b/demux/ebml.h index 86a40092b6..e881731295 100644 --- a/demux/ebml.h +++ b/demux/ebml.h @@ -78,6 +78,9 @@ struct ebml_parse_ctx { #define EBML_UINT_INVALID UINT64_MAX #define EBML_INT_INVALID INT64_MAX +/* Block Addition Mappings */ +#define MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35 4 + bool ebml_is_mkv_level1_id(uint32_t id); uint32_t ebml_read_id (stream_t *s); uint64_t ebml_read_length (stream_t *s); diff --git a/demux/packet.c b/demux/packet.c index ed43729b87..93f64e844a 100644 --- a/demux/packet.c +++ b/demux/packet.c @@ -21,11 +21,13 @@ #include <assert.h> #include <libavcodec/avcodec.h> +#include <libavutil/hdr_dynamic_metadata.h> #include <libavutil/intreadwrite.h> #include "common/av_common.h" #include "common/common.h" #include "demux.h" +#include "demux/ebml.h" #include "packet.h" @@ -232,9 +234,57 @@ int demux_packet_add_blockadditional(struct demux_packet *dp, uint64_t id, { if (!dp->avpacket) return -1; - uint8_t *sd = av_packet_new_side_data(dp->avpacket, - AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, - 8 + size); + + switch (id) { +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 5, 100) + case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: { + static const uint8_t ITU_T_T35_COUNTRY_CODE_US = 0xB5; + static const uint16_t ITU_T_T35_PROVIDER_CODE_SMTPE = 0x3C; + + if (size < 6) + break; + + uint8_t *p = data; + + uint8_t country_code = AV_RB8(p); + p += sizeof(country_code); + uint16_t provider_code = AV_RB16(p); + p += sizeof(provider_code); + + if (country_code != ITU_T_T35_COUNTRY_CODE_US || + provider_code != ITU_T_T35_PROVIDER_CODE_SMTPE) + break; + + uint16_t provider_oriented_code = AV_RB16(p); + p += sizeof(provider_oriented_code); + uint8_t application_identifier = AV_RB8(p); + p += sizeof(application_identifier); + + if (provider_oriented_code != 1 || application_identifier != 4) + break; + + size_t hdrplus_size; + AVDynamicHDRPlus *hdrplus = av_dynamic_hdr_plus_alloc(&hdrplus_size); + MP_HANDLE_OOM(hdrplus); + + if (av_dynamic_hdr_plus_from_t35(hdrplus, p, size - (p - (uint8_t *)data)) < 0 || + av_packet_add_side_data(dp->avpacket, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, + (uint8_t *)hdrplus, hdrplus_size) < 0) + { + av_free(hdrplus); + return -1; + } + + return 0; + } +#endif + default: + break; + } + + uint8_t *sd = av_packet_new_side_data(dp->avpacket, + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + 8 + size); if (!sd) return -1; AV_WB64(sd, id); diff --git a/demux/stheader.h b/demux/stheader.h index 438ef7db41..6025aa5a0c 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -72,6 +72,18 @@ struct mp_codec_params { // E.g. "h264" (usually corresponds to AVCodecDescriptor.name) const char *codec; + // Usually corresponds to AVCodecDescriptor.long_name + const char *codec_desc; + + // Corresponding codec profile + const char *codec_profile; + + // E.g. "h264" (usually corresponds to AVCodec.name) + const char *decoder; + + // Usually corresponds to AVCodec.long_name + const char *decoder_desc; + // Usually a FourCC, exact meaning depends on codec. unsigned int codec_tag; @@ -109,6 +121,10 @@ struct mp_codec_params { struct pl_color_repr repr; // color representaion info where available struct mp_rect crop; // crop to be applied + bool dovi; + uint8_t dv_profile; + uint8_t dv_level; + // STREAM_VIDEO + STREAM_AUDIO int bits_per_coded_sample; char *format_name; // pixel format (video) or sample format (audio) |