summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--demux/cache.c8
-rw-r--r--demux/codec_tags.c79
-rw-r--r--demux/codec_tags.h2
-rw-r--r--demux/demux.c4
-rw-r--r--demux/demux_disc.c2
-rw-r--r--demux/demux_lavf.c25
-rw-r--r--demux/demux_libarchive.c2
-rw-r--r--demux/demux_mf.c76
-rw-r--r--demux/demux_mkv.c123
-rw-r--r--demux/demux_playlist.c8
-rw-r--r--demux/packet.h6
-rw-r--r--demux/stheader.h14
12 files changed, 205 insertions, 144 deletions
diff --git a/demux/cache.c b/demux/cache.c
index 562eab0..6398f61 100644
--- a/demux/cache.c
+++ b/demux/cache.c
@@ -26,6 +26,7 @@
#include "common/msg.h"
#include "common/av_common.h"
#include "demux.h"
+#include "misc/io_utils.h"
#include "options/path.h"
#include "options/m_config.h"
#include "options/m_option.h"
@@ -214,7 +215,7 @@ int64_t demux_cache_write(struct demux_cache *cache, struct demux_packet *dp)
}
assert(!dp->is_cached);
- assert(dp->len >= 0 && dp->len <= INT32_MAX);
+ assert(dp->len <= INT32_MAX);
assert(dp->avpacket->flags >= 0 && dp->avpacket->flags <= INT32_MAX);
assert(dp->avpacket->side_data_elems >= 0 &&
dp->avpacket->side_data_elems <= INT32_MAX);
@@ -260,7 +261,7 @@ int64_t demux_cache_write(struct demux_cache *cache, struct demux_packet *dp)
for (int n = 0; n < dp->avpacket->side_data_elems; n++) {
AVPacketSideData *sd = &dp->avpacket->side_data[n];
- assert(sd->size >= 0 && sd->size <= INT32_MAX);
+ assert(sd->size <= INT32_MAX);
assert(sd->type >= 0 && sd->type <= INT32_MAX);
struct sd_header sd_hd = {
@@ -293,9 +294,6 @@ struct demux_packet *demux_cache_read(struct demux_cache *cache, uint64_t pos)
if (!read_raw(cache, &hd, sizeof(hd)))
return NULL;
- if (hd.data_len >= (size_t)-1)
- return NULL;
-
struct demux_packet *dp = new_demux_packet(hd.data_len);
if (!dp)
goto fail;
diff --git a/demux/codec_tags.c b/demux/codec_tags.c
index 55700d9..d118fbe 100644
--- a/demux/codec_tags.c
+++ b/demux/codec_tags.c
@@ -48,8 +48,8 @@ static const char *lookup_tag(int type, uint32_t tag)
/*
* As seen in the following page:
*
- * https://web.archive.org/web/20220406060153/
- * http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html
+ * <https://web.archive.org/web/20220406060153/
+ * http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html>
*
* Note that the GUID struct in the above citation has its
* integers encoded in little-endian format, which means that
@@ -180,81 +180,6 @@ void mp_set_pcm_codec(struct mp_codec_params *c, bool sign, bool is_float,
c->codec = talloc_strdup(c, codec);
}
-// map file extension/type to an image codec name
-static const char *const type_to_codec[][2] = {
- { "bmp", "bmp" },
- { "dpx", "dpx" },
- { "j2c", "jpeg2000" },
- { "j2k", "jpeg2000" },
- { "jp2", "jpeg2000" },
- { "jpc", "jpeg2000" },
- { "jpeg", "mjpeg" },
- { "jpg", "mjpeg" },
- { "jps", "mjpeg" },
- { "jls", "ljpeg" },
- { "thm", "mjpeg" },
- { "db", "mjpeg" },
- { "pcd", "photocd" },
- { "pfm", "pfm" },
- { "phm", "phm" },
- { "hdr", "hdr" },
- { "pcx", "pcx" },
- { "png", "png" },
- { "pns", "png" },
- { "ptx", "ptx" },
- { "tga", "targa" },
- { "tif", "tiff" },
- { "tiff", "tiff" },
- { "sgi", "sgi" },
- { "sun", "sunrast" },
- { "ras", "sunrast" },
- { "rs", "sunrast" },
- { "ra", "sunrast" },
- { "im1", "sunrast" },
- { "im8", "sunrast" },
- { "im24", "sunrast" },
- { "im32", "sunrast" },
- { "sunras", "sunrast" },
- { "xbm", "xbm" },
- { "pam", "pam" },
- { "pbm", "pbm" },
- { "pgm", "pgm" },
- { "pgmyuv", "pgmyuv" },
- { "ppm", "ppm" },
- { "pnm", "ppm" },
- { "gif", "gif" },
- { "pix", "brender_pix" },
- { "exr", "exr" },
- { "pic", "pictor" },
- { "qoi", "qoi" },
- { "xface", "xface" },
- { "xwd", "xwd" },
- { "svg", "svg" },
- {0}
-};
-
-bool mp_codec_is_image(const char *codec)
-{
- if (codec) {
- for (int n = 0; type_to_codec[n][0]; n++) {
- if (strcasecmp(type_to_codec[n][1], codec) == 0)
- return true;
- }
- }
- return false;
-}
-
-const char *mp_map_type_to_image_codec(const char *type)
-{
- if (type) {
- for (int n = 0; type_to_codec[n][0]; n++) {
- if (strcasecmp(type_to_codec[n][0], type) == 0)
- return type_to_codec[n][1];
- }
- }
- return NULL;
-};
-
static const char *const mimetype_to_codec[][2] = {
{"image/apng", "apng"},
{"image/avif", "av1"},
diff --git a/demux/codec_tags.h b/demux/codec_tags.h
index 8fc49df..147760b 100644
--- a/demux/codec_tags.h
+++ b/demux/codec_tags.h
@@ -28,8 +28,6 @@ void mp_set_codec_from_tag(struct mp_codec_params *c);
void mp_set_pcm_codec(struct mp_codec_params *c, bool sign, bool is_float,
int bits, bool is_be);
-bool mp_codec_is_image(const char *codec);
-const char *mp_map_type_to_image_codec(const char *type);
const char *mp_map_mimetype_to_video_codec(const char *mimetype);
#endif
diff --git a/demux/demux.c b/demux/demux.c
index 256e1b6..9aa63bc 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -367,7 +367,7 @@ struct demux_stream {
bool eager; // try to keep at least 1 packet queued
// if false, this stream is disabled, or passively
// read (like subtitles)
- bool still_image; // stream has still video images
+ bool still_image; // stream consists of multiple sparse still images
bool refreshing; // finding old position after track switches
bool eof; // end of demuxed stream? (true if no more packets)
@@ -663,7 +663,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);
diff --git a/demux/demux_disc.c b/demux/demux_disc.c
index 3dfff45..8cd4b7b 100644
--- a/demux/demux_disc.c
+++ b/demux/demux_disc.c
@@ -94,7 +94,7 @@ static void add_dvd_streams(demuxer_t *demuxer)
// emulate the extradata
struct mp_csp_params csp = MP_CSP_PARAMS_DEFAULTS;
- struct mp_cmat cmatrix;
+ struct pl_transform3x3 cmatrix;
mp_get_csp_matrix(&csp, &cmatrix);
char *s = talloc_strdup(sh, "");
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 663fab4..fa9fd5c 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -29,14 +29,15 @@
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
+
#include <libavutil/avutil.h>
#include <libavutil/avstring.h>
-#include <libavutil/mathematics.h>
-#include <libavutil/replaygain.h>
#include <libavutil/display.h>
-#include <libavutil/opt.h>
-
#include <libavutil/dovi_meta.h>
+#include <libavutil/mathematics.h>
+#include <libavutil/opt.h>
+#include <libavutil/pixdesc.h>
+#include <libavutil/replaygain.h>
#include "audio/chmap_avchannel.h"
@@ -146,7 +147,6 @@ struct format_hack {
// segment, with e.g. HLS, player knows about the playlist main file only).
bool clear_filepos : 1;
bool linearize_audio_ts : 1;// compensate timestamp resets (audio only)
- bool fix_editlists : 1;
bool is_network : 1;
bool no_seek : 1;
bool no_pcm_seek : 1;
@@ -175,8 +175,7 @@ static const struct format_hack format_hacks[] = {
{"mxf", .use_stream_ids = true},
{"avi", .use_stream_ids = true},
{"asf", .use_stream_ids = true},
- {"mp4", .skipinfo = true, .fix_editlists = true, .no_pcm_seek = true,
- .use_stream_ids = true},
+ {"mp4", .skipinfo = true, .no_pcm_seek = true, .use_stream_ids = true},
{"matroska", .skipinfo = true, .no_pcm_seek = true, .use_stream_ids = true},
{"v4l2", .no_seek = true},
@@ -512,6 +511,10 @@ static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
break;
}
+ // AVIF always needs to find stream info
+ if (bstrcasecmp0(ext, "avif") == 0)
+ priv->format_hack.skipinfo = false;
+
if (score >= lavfdopts->probescore)
break;
@@ -673,6 +676,7 @@ static bool is_image(AVStream *st, bool attached_picture, const AVInputFormat *a
bstr_endswith0(bstr0(avif->name), "_pipe") ||
strcmp(avif->name, "alias_pix") == 0 ||
strcmp(avif->name, "gif") == 0 ||
+ strcmp(avif->name, "ico") == 0 ||
strcmp(avif->name, "image2pipe") == 0 ||
(st->codecpar->codec_id == AV_CODEC_ID_AV1 && st->nb_frames == 1)
);
@@ -723,6 +727,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
sh->codec->samplerate = codec->sample_rate;
sh->codec->bitrate = codec->bit_rate;
+ sh->codec->format_name = talloc_strdup(sh, av_get_sample_fmt_name(codec->format));
double delay = 0;
if (codec->sample_rate > 0)
@@ -761,6 +766,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
sh->codec->disp_w = codec->width;
sh->codec->disp_h = codec->height;
+ sh->codec->format_name = talloc_strdup(sh, av_get_pix_fmt_name(codec->format));
if (st->avg_frame_rate.num)
sh->codec->fps = av_q2d(st->avg_frame_rate);
if (is_image(st, sh->attached_picture, priv->avif)) {
@@ -1065,9 +1071,6 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
guess_and_set_vobsub_name(demuxer, &dopts);
- if (priv->format_hack.fix_editlists)
- av_dict_set(&dopts, "advanced_editlist", "0", 0);
-
avfc->interrupt_callback = (AVIOInterruptCB){
.callback = interrupt_cb,
.opaque = demuxer,
@@ -1267,8 +1270,6 @@ static bool demux_lavf_read_packet(struct demuxer *demux,
dp->duration = pkt->duration * av_q2d(st->time_base);
dp->pos = pkt->pos;
dp->keyframe = pkt->flags & AV_PKT_FLAG_KEY;
- if (pkt->flags & AV_PKT_FLAG_DISCARD)
- MP_ERR(demux, "Edit lists are not correctly supported (FFmpeg issue).\n");
av_packet_unref(pkt);
if (priv->format_hack.clear_filepos)
diff --git a/demux/demux_libarchive.c b/demux/demux_libarchive.c
index ec50498..a85e40f 100644
--- a/demux/demux_libarchive.c
+++ b/demux/demux_libarchive.c
@@ -91,7 +91,7 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
qsort(files, num_files, sizeof(files[0]), cmp_filename);
for (int n = 0; n < num_files; n++)
- playlist_add_file(pl, files[n]);
+ playlist_append_file(pl, files[n]);
playlist_set_stream_flags(pl, demuxer->stream_origin);
diff --git a/demux/demux_mf.c b/demux/demux_mf.c
index 8f7cb70..d971f04 100644
--- a/demux/demux_mf.c
+++ b/demux/demux_mf.c
@@ -95,7 +95,6 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
}
free_stream(s);
- mp_info(log, "number of files: %d\n", mf->nr_of_files);
goto exit_mf;
}
mp_info(log, "%s is not indirect filelist\n", filename + 1);
@@ -117,7 +116,6 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
}
talloc_free(fname2);
}
- mp_info(log, "number of files: %d\n", mf->nr_of_files);
goto exit_mf;
}
@@ -143,7 +141,6 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
continue;
mf_add(mf, gg.gl_pathv[i]);
}
- mp_info(log, "number of files: %d\n", mf->nr_of_files);
globfree(&gg);
goto exit_mf;
}
@@ -189,7 +186,9 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
// nspec==0 (zero specifiers) is rejected because fname wouldn't advance.
if (bad_spec || nspec != 1) {
- mp_err(log, "unsupported expr format: '%s'\n", filename);
+ mp_err(log,
+ "unsupported expr format: '%s' - exactly one format specifier of the form %%[.][NUM]d is expected\n",
+ filename);
goto exit_mf;
}
@@ -208,9 +207,8 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
}
}
- mp_info(log, "number of files: %d\n", mf->nr_of_files);
-
exit_mf:
+ mp_info(log, "number of files: %d\n", mf->nr_of_files);
return mf;
}
@@ -284,6 +282,65 @@ static bool demux_mf_read_packet(struct demuxer *demuxer,
return true;
}
+// map file extension/type to a codec name
+
+static const struct {
+ const char *type;
+ const char *codec;
+} type2format[] = {
+ { "bmp", "bmp" },
+ { "dpx", "dpx" },
+ { "j2c", "jpeg2000" },
+ { "j2k", "jpeg2000" },
+ { "jp2", "jpeg2000" },
+ { "jpc", "jpeg2000" },
+ { "jpeg", "mjpeg" },
+ { "jpg", "mjpeg" },
+ { "jps", "mjpeg" },
+ { "jls", "ljpeg" },
+ { "thm", "mjpeg" },
+ { "db", "mjpeg" },
+ { "pcd", "photocd" },
+ { "pfm", "pfm" },
+ { "phm", "phm" },
+ { "hdr", "hdr" },
+ { "pcx", "pcx" },
+ { "png", "png" },
+ { "pns", "png" },
+ { "ptx", "ptx" },
+ { "tga", "targa" },
+ { "tif", "tiff" },
+ { "tiff", "tiff" },
+ { "sgi", "sgi" },
+ { "sun", "sunrast" },
+ { "ras", "sunrast" },
+ { "rs", "sunrast" },
+ { "ra", "sunrast" },
+ { "im1", "sunrast" },
+ { "im8", "sunrast" },
+ { "im24", "sunrast" },
+ { "im32", "sunrast" },
+ { "sunras", "sunrast" },
+ { "xbm", "xbm" },
+ { "pam", "pam" },
+ { "pbm", "pbm" },
+ { "pgm", "pgm" },
+ { "pgmyuv", "pgmyuv" },
+ { "ppm", "ppm" },
+ { "pnm", "ppm" },
+ { "gif", "gif" }, // usually handled by demux_lavf
+ { "pix", "brender_pix" },
+ { "exr", "exr" },
+ { "pic", "pictor" },
+ { "qoi", "qoi" },
+ { "xface", "xface" },
+ { "xwd", "xwd" },
+ { "svg", "svg" },
+ { "webp", "webp" },
+ { "jxl", "jpegxl" },
+ {0}
+};
+
static const char *probe_format(mf_t *mf, char *type, enum demux_check check)
{
if (check > DEMUX_CHECK_REQUEST)
@@ -294,9 +351,10 @@ static const char *probe_format(mf_t *mf, char *type, enum demux_check check)
if (p)
type = p + 1;
}
- const char *codec = mp_map_type_to_image_codec(type);
- if (codec)
- return codec;
+ for (int i = 0; type2format[i].type; i++) {
+ if (type && strcasecmp(type, type2format[i].type) == 0)
+ return type2format[i].codec;
+ }
if (check == DEMUX_CHECK_REQUEST) {
if (!org_type) {
MP_ERR(mf, "file type was not set! (try --mf-type=ext)\n");
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 41226c5..443cec0 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -36,6 +36,8 @@
#include <libavcodec/avcodec.h>
#include <libavcodec/version.h>
+#include <libplacebo/utils/libav.h>
+
#include "config.h"
#if HAVE_ZLIB
@@ -108,10 +110,12 @@ typedef struct mkv_track {
double v_frate;
uint32_t colorspace;
int stereo_mode;
- struct mp_colorspace color;
+ 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;
@@ -387,6 +391,10 @@ static bstr demux_mkv_decode(struct mp_log *log, mkv_track_t *track,
}
size = dstlen - out_avail;
} else if (enc->comp_algo == 3) {
+ if (enc->comp_settings_len == 0 || !enc->comp_settings) {
+ mp_warn(log, "missing comp_settings, unable to reconstruct the data.\n");
+ goto error;
+ }
dest = talloc_size(track->parser_tmp, size + enc->comp_settings_len);
memcpy(dest, enc->comp_settings, enc->comp_settings_len);
memcpy(dest + enc->comp_settings_len, src, size);
@@ -399,6 +407,8 @@ static bstr demux_mkv_decode(struct mp_log *log, mkv_track_t *track,
talloc_free(src);
if (!size)
dest = NULL;
+ if (!dest)
+ size = 0;
return (bstr){dest, size};
}
@@ -573,24 +583,24 @@ static void parse_trackcolour(struct demuxer *demuxer, struct mkv_track *track,
// 23001-8:2013/DCOR1, which is the same order used by libavutil/pixfmt.h,
// so we can just re-use our avcol_ conversion functions.
if (colour->n_matrix_coefficients) {
- track->color.space = avcol_spc_to_mp_csp(colour->matrix_coefficients);
+ track->repr.sys = pl_system_from_av(colour->matrix_coefficients);
MP_DBG(demuxer, "| + Matrix: %s\n",
- m_opt_choice_str(mp_csp_names, track->color.space));
+ m_opt_choice_str(pl_csp_names, track->repr.sys));
}
if (colour->n_primaries) {
- track->color.primaries = avcol_pri_to_mp_csp_prim(colour->primaries);
+ track->color.primaries = pl_primaries_from_av(colour->primaries);
MP_DBG(demuxer, "| + Primaries: %s\n",
- m_opt_choice_str(mp_csp_prim_names, track->color.primaries));
+ m_opt_choice_str(pl_csp_prim_names, track->color.primaries));
}
if (colour->n_transfer_characteristics) {
- track->color.gamma = avcol_trc_to_mp_csp_trc(colour->transfer_characteristics);
+ track->color.transfer = pl_transfer_from_av(colour->transfer_characteristics);
MP_DBG(demuxer, "| + Gamma: %s\n",
- m_opt_choice_str(mp_csp_trc_names, track->color.gamma));
+ m_opt_choice_str(pl_csp_trc_names, track->color.transfer));
}
if (colour->n_range) {
- track->color.levels = avcol_range_to_mp_csp_levels(colour->range);
+ track->repr.levels = pl_levels_from_av(colour->range);
MP_DBG(demuxer, "| + Levels: %s\n",
- m_opt_choice_str(mp_csp_levels_names, track->color.levels));
+ m_opt_choice_str(pl_csp_levels_names, track->repr.levels));
}
if (colour->n_max_cll) {
track->color.hdr.max_cll = colour->max_cll;
@@ -649,15 +659,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,
@@ -795,7 +820,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 {
@@ -1082,8 +1110,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),
@@ -1438,6 +1466,7 @@ static const char *const mkv_video_tags[][2] = {
{"V_PNG", "png"},
{"V_AVS2", "avs2"},
{"V_AVS3", "avs3"},
+ {"V_FFV1", "ffv1"},
{0}
};
@@ -1523,10 +1552,6 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
}
const char *codec = sh_v->codec ? sh_v->codec : "";
- if (mp_codec_is_image(codec)) {
- sh->still_image = true;
- sh->image = true;
- }
if (!strcmp(codec, "mjpeg")) {
sh_v->codec_tag = MKTAG('m', 'j', 'p', 'g');
track->require_keyframes = true;
@@ -1569,8 +1594,8 @@ 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;
}
@@ -1647,6 +1672,7 @@ static void parse_flac_chmap(struct mp_chmap *channels, unsigned char *data,
}
static const char *const mkv_audio_tags[][2] = {
+ { "A_MPEG/L1", "mp1" },
{ "A_MPEG/L2", "mp2" },
{ "A_MPEG/L3", "mp3" },
{ "A_AC3", "ac3" },
@@ -1835,7 +1861,7 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
goto error;
const char *codec = sh_a->codec;
- if (!strcmp(codec, "mp2") || !strcmp(codec, "mp3") ||
+ if (!strcmp(codec, "mp1") || !strcmp(codec, "mp2") || !strcmp(codec, "mp3") ||
!strcmp(codec, "truehd") || !strcmp(codec, "eac3"))
{
mkv_demuxer_t *mkv_d = demuxer->priv;
@@ -1921,6 +1947,7 @@ static const char *const mkv_sub_tag[][2] = {
{ "S_TEXT/ASCII", "subrip"},
{ "S_TEXT/UTF8", "subrip"},
{ "S_HDMV/PGS", "hdmv_pgs_subtitle"},
+ { "S_HDMV/TEXTST", "hdmv_text_subtitle"},
{ "D_WEBVTT/SUBTITLES", "webvtt-webm"},
{ "D_WEBVTT/CAPTIONS", "webvtt-webm"},
{ "S_TEXT/WEBVTT", "webvtt"},
@@ -1962,7 +1989,7 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track)
sh->codec->extradata = track->private_data;
sh->codec->extradata_size = track->private_size;
- if (!strcmp(sh->codec->codec, "arib_caption") && track->private_size >= 3) {
+ if (subtitle_type && !strcmp(sh->codec->codec, "arib_caption") && track->private_size >= 3) {
struct AVCodecParameters **lavp = talloc_ptrtype(track, lavp);
talloc_set_destructor(lavp, avcodec_par_destructor);
@@ -2002,6 +2029,39 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track)
return 0;
}
+// Workaround for broken files that don't set attached_picture
+static void probe_if_image(demuxer_t *demuxer)
+{
+ mkv_demuxer_t *mkv_d = demuxer->priv;
+
+ for (int n = 0; n < mkv_d->num_tracks; n++) {
+ int video_blocks = 0;
+ mkv_track_t *track = mkv_d->tracks[n];
+ struct sh_stream *sh = track->stream;
+
+ if (!sh || sh->type != STREAM_VIDEO || sh->image)
+ continue;
+
+ 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
+ if (video_blocks > 1)
+ break;
+ }
+
+ // Assume still image
+ if (video_blocks == 1)
+ sh->image = true;
+ }
+}
+
static void probe_x264_garbage(demuxer_t *demuxer)
{
mkv_demuxer_t *mkv_d = demuxer->priv;
@@ -2034,6 +2094,8 @@ static void probe_x264_garbage(demuxer_t *demuxer)
bstr sblock = {block->laces[0]->data, block->laces[0]->size};
bstr nblock = demux_mkv_decode(demuxer->log, track, sblock, 1);
+ if (!nblock.len)
+ continue;
sh->codec->first_packet = new_demux_packet_from(nblock.start, nblock.len);
talloc_steal(mkv_d, sh->codec->first_packet);
@@ -2254,6 +2316,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
if (mkv_d->opts->probe_duration)
probe_last_timestamp(demuxer, start_pos);
probe_x264_garbage(demuxer);
+ probe_if_image(demuxer);
return 0;
}
@@ -2795,6 +2858,8 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
bstr block = {data->data, data->size};
bstr nblock = demux_mkv_decode(demuxer->log, track, block, 1);
+ if (!nblock.len)
+ break;
if (block.start != nblock.start || block.len != nblock.len) {
// (avoidable copy of the entire data)
@@ -2944,20 +3009,22 @@ static int read_next_block_into_queue(demuxer_t *demuxer)
if (end > mkv_d->cluster_end)
goto find_next_cluster;
int res = read_block_group(demuxer, end, &block);
- if (res < 0)
- goto find_next_cluster;
if (res > 0)
goto add_block;
+ free_block(&block);
+ if (res < 0)
+ goto find_next_cluster;
break;
}
case MATROSKA_ID_SIMPLEBLOCK: {
block = (struct block_info){ .simple = true };
int res = read_block(demuxer, mkv_d->cluster_end, &block);
- if (res < 0)
- goto find_next_cluster;
if (res > 0)
goto add_block;
+ free_block(&block);
+ if (res < 0)
+ goto find_next_cluster;
break;
}
diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c
index 63355be..66be4b1 100644
--- a/demux/demux_playlist.c
+++ b/demux/demux_playlist.c
@@ -202,7 +202,7 @@ static void pl_free_line(struct pl_parser *p, bstr line)
static void pl_add(struct pl_parser *p, bstr entry)
{
char *s = bstrto0(NULL, entry);
- playlist_add_file(p->pl, s);
+ playlist_append_file(p->pl, s);
talloc_free(s);
}
@@ -266,7 +266,7 @@ ok:
talloc_free(fn);
e->title = talloc_steal(e, title);
title = NULL;
- playlist_add(p->pl, e);
+ playlist_insert_at(p->pl, e, NULL);
}
pl_free_line(p, line);
line = pl_get_line(p);
@@ -296,7 +296,7 @@ static int parse_ref_init(struct pl_parser *p)
bstr burl = bstr0(p->s->url);
if (bstr_eatstart0(&burl, "http://") && check_mimetype(p->s, mmsh_types)) {
MP_INFO(p, "Redirecting to mmsh://\n");
- playlist_add_file(p->pl, talloc_asprintf(p, "mmsh://%.*s", BSTR_P(burl)));
+ playlist_append_file(p->pl, talloc_asprintf(p, "mmsh://%.*s", BSTR_P(burl)));
return 0;
}
@@ -456,7 +456,7 @@ static bool scan_dir(struct pl_parser *p, char *path,
scan_dir(p, file, dir_stack, num_dir_stack + 1);
}
else {
- playlist_add_file(p->pl, dir_entries[n].path);
+ playlist_append_file(p->pl, dir_entries[n].path);
}
}
diff --git a/demux/packet.h b/demux/packet.h
index cd1183d..8087216 100644
--- a/demux/packet.h
+++ b/demux/packet.h
@@ -58,6 +58,12 @@ typedef struct demux_packet {
struct mp_codec_params *codec; // set to non-NULL iff segmented is set
double start, end; // set to non-NOPTS iff segmented is set
+ // subtitles only
+ bool animated;
+ bool seen;
+ int seen_pos;
+ double sub_duration;
+
// private
struct demux_packet *next;
struct AVPacket *avpacket; // keep the buffer allocation and sidedata
diff --git a/demux/stheader.h b/demux/stheader.h
index 1bc036d..4f33bbc 100644
--- a/demux/stheader.h
+++ b/demux/stheader.h
@@ -49,7 +49,7 @@ struct sh_stream {
bool visual_impaired_track; // container flag
bool hearing_impaired_track;// container flag
bool image; // video stream is an image
- bool still_image; // video stream contains still images
+ bool still_image; // video consists of multiple sparse still images
int hls_bitrate;
int program_id;
@@ -72,6 +72,12 @@ 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;
+
// Usually a FourCC, exact meaning depends on codec.
unsigned int codec_tag;
@@ -105,11 +111,13 @@ struct mp_codec_params {
int disp_w, disp_h; // display size
int rotate; // intended display rotation, in degrees, [0, 359]
int stereo_mode; // mp_stereo3d_mode (0 if none/unknown)
- struct mp_colorspace color; // colorspace info where available
- struct mp_rect crop; // crop to be applied
+ struct pl_color_space color; // colorspace info where available
+ struct pl_color_repr repr; // color representaion info where available
+ struct mp_rect crop; // crop to be applied
// STREAM_VIDEO + STREAM_AUDIO
int bits_per_coded_sample;
+ char *format_name; // pixel format (video) or sample format (audio)
// STREAM_SUB
double frame_based; // timestamps are frame-based (and this is the