#include <zlib.h>
#endif
+#include "qtpalette.h"
+
typedef enum {
EBML_NONE,
EBML_UINT,
/* WebM DASH Manifest live flag/ */
int is_live;
+
+ uint32_t palette[AVPALETTE_COUNT];
+ int has_palette;
} MatroskaDemuxContext;
typedef struct MatroskaBlock {
}
}
+static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id)
+{
+ const AVCodecTag *codec_tags;
+
+ codec_tags = track->type == MATROSKA_TRACK_TYPE_VIDEO ?
+ ff_codec_movvideo_tags : ff_codec_movaudio_tags;
+
+ /* Normalize noncompliant private data that starts with the fourcc
+ * by expanding/shifting the data by 4 bytes and storing the data
+ * size at the start. */
+ if (ff_codec_get_id(codec_tags, AV_RL32(track->codec_priv.data))) {
+ uint8_t *p = av_realloc(track->codec_priv.data,
+ track->codec_priv.size + 4);
+ if (!p)
+ return AVERROR(ENOMEM);
+ memmove(p + 4, p, track->codec_priv.size);
+ track->codec_priv.data = p;
+ track->codec_priv.size += 4;
+ AV_WB32(track->codec_priv.data, track->codec_priv.size);
+ }
+
+ *fourcc = AV_RL32(track->codec_priv.data + 4);
+ *codec_id = ff_codec_get_id(codec_tags, *fourcc);
+
+ return 0;
+}
+
static int matroska_parse_tracks(AVFormatContext *s)
{
MatroskaDemuxContext *matroska = s->priv_data;
fourcc = st->codec->codec_tag;
extradata_offset = FFMIN(track->codec_priv.size, 18);
} else if (!strcmp(track->codec_id, "A_QUICKTIME")
- && (track->codec_priv.size >= 86)
+ /* Normally 36, but allow noncompliant private data */
+ && (track->codec_priv.size >= 32)
&& (track->codec_priv.data)) {
- fourcc = AV_RL32(track->codec_priv.data + 4);
- codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);
- if (ff_codec_get_id(ff_codec_movaudio_tags, AV_RL32(track->codec_priv.data))) {
- fourcc = AV_RL32(track->codec_priv.data);
- codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);
+ uint16_t sample_size;
+ int ret = get_qt_codec(track, &fourcc, &codec_id);
+ if (ret < 0)
+ return ret;
+ sample_size = AV_RB16(track->codec_priv.data + 26);
+ if (fourcc == 0) {
+ if (sample_size == 8) {
+ fourcc = MKTAG('r','a','w',' ');
+ codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);
+ } else if (sample_size == 16) {
+ fourcc = MKTAG('t','w','o','s');
+ codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);
+ }
}
+ if ((fourcc == MKTAG('t','w','o','s') ||
+ fourcc == MKTAG('s','o','w','t')) &&
+ sample_size == 8)
+ codec_id = AV_CODEC_ID_PCM_S8;
} else if (!strcmp(track->codec_id, "V_QUICKTIME") &&
(track->codec_priv.size >= 21) &&
(track->codec_priv.data)) {
- fourcc = AV_RL32(track->codec_priv.data + 4);
- codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc);
- if (ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(track->codec_priv.data))) {
- fourcc = AV_RL32(track->codec_priv.data);
+ int ret = get_qt_codec(track, &fourcc, &codec_id);
+ if (ret < 0)
+ return ret;
+ if (codec_id == AV_CODEC_ID_NONE && AV_RL32(track->codec_priv.data+4) == AV_RL32("SMI ")) {
+ fourcc = MKTAG('S','V','Q','3');
codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc);
}
- if (codec_id == AV_CODEC_ID_NONE && AV_RL32(track->codec_priv.data+4) == AV_RL32("SMI "))
- codec_id = AV_CODEC_ID_SVQ3;
if (codec_id == AV_CODEC_ID_NONE) {
char buf[32];
av_get_codec_tag_string(buf, sizeof(buf), fourcc);
av_log(matroska->ctx, AV_LOG_ERROR,
"mov FourCC not found %s.\n", buf);
}
+ if (track->codec_priv.size >= 86) {
+ bit_depth = AV_RB16(track->codec_priv.data + 82);
+ ffio_init_context(&b, track->codec_priv.data,
+ track->codec_priv.size,
+ 0, NULL, NULL, NULL, NULL);
+ if (ff_get_qtpalette(codec_id, &b, matroska->palette)) {
+ bit_depth &= 0x1F;
+ matroska->has_palette = 1;
+ }
+ }
} else if (codec_id == AV_CODEC_ID_PCM_S16BE) {
switch (track->audio.bitdepth) {
case 8:
if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
MatroskaTrackPlane *planes = track->operation.combine_planes.elem;
- int display_width_mul = 1;
+ int display_width_mul = 1;
int display_height_mul = 1;
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
av_reduce(&st->sample_aspect_ratio.num,
&st->sample_aspect_ratio.den,
- st->codec->height * track->video.display_width * display_width_mul,
+ st->codec->height * track->video.display_width * display_width_mul,
st->codec->width * track->video.display_height * display_height_mul,
255);
if (st->codec->codec_id != AV_CODEC_ID_HEVC)
if (matroska->num_packets > 0) {
memcpy(pkt, matroska->packets[0], sizeof(AVPacket));
av_freep(&matroska->packets[0]);
+ if (matroska->has_palette) {
+ uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
+ if (!pal) {
+ av_log(matroska->ctx, AV_LOG_ERROR, "Cannot append palette to packet\n");
+ } else {
+ memcpy(pal, matroska->palette, AVPALETTE_SIZE);
+ }
+ matroska->has_palette = 0;
+ }
if (matroska->num_packets > 1) {
void *newpackets;
memmove(&matroska->packets[0], &matroska->packets[1],