summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
Diffstat (limited to 'demux')
-rw-r--r--demux/cache.c1
-rw-r--r--demux/demux.c87
-rw-r--r--demux/demux.h11
-rw-r--r--demux/demux_cue.c1
-rw-r--r--demux/demux_edl.c2
-rw-r--r--demux/demux_lavf.c20
-rw-r--r--demux/demux_mf.c2
-rw-r--r--demux/demux_mkv.c175
-rw-r--r--demux/demux_mkv_timeline.c3
-rw-r--r--demux/demux_playlist.c2
-rw-r--r--demux/demux_raw.c1
-rw-r--r--demux/ebml.h3
-rw-r--r--demux/packet.c56
-rw-r--r--demux/stheader.h16
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)