Commit e6ec9212 authored by Kirill Gavrilov's avatar Kirill Gavrilov Committed by Michael Niedermayer

matroska: switch stereo mode from int to string and add support in the demuxer too

parent 69a83da5
......@@ -79,6 +79,11 @@
#define MATROSKA_ID_TRACKTYPE 0x83
#define MATROSKA_ID_TRACKVIDEO 0xE0
#define MATROSKA_ID_TRACKAUDIO 0xE1
#define MATROSKA_ID_TRACKOPERATION 0xE2
#define MATROSKA_ID_TRACKCOMBINEPLANES 0xE3
#define MATROSKA_ID_TRACKPLANE 0xE4
#define MATROSKA_ID_TRACKPLANEUID 0xE5
#define MATROSKA_ID_TRACKPLANETYPE 0xE6
#define MATROSKA_ID_CODECID 0x86
#define MATROSKA_ID_CODECPRIVATE 0x63A2
#define MATROSKA_ID_CODECNAME 0x258688
......
......@@ -112,6 +112,7 @@ typedef struct {
uint64_t pixel_width;
uint64_t pixel_height;
uint64_t fourcc;
uint64_t stereoMode;
} MatroskaTrackVideo;
typedef struct {
......@@ -131,6 +132,16 @@ typedef struct {
uint8_t *buf;
} MatroskaTrackAudio;
typedef struct {
uint64_t uid;
uint64_t type;
} MatroskaTrackPlane;
typedef struct {
EbmlList combine_planes;
/*EbmlList join_blocks;*/
} MatroskaTrackOperation;
typedef struct {
uint64_t num;
uint64_t uid;
......@@ -145,6 +156,7 @@ typedef struct {
uint64_t flag_forced;
MatroskaTrackVideo video;
MatroskaTrackAudio audio;
MatroskaTrackOperation operation;
EbmlList encodings;
AVStream *stream;
......@@ -291,13 +303,13 @@ static EbmlSyntax matroska_track_video[] = {
{ MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_width) },
{ MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_height) },
{ MATROSKA_ID_VIDEOCOLORSPACE, EBML_UINT, 0, offsetof(MatroskaTrackVideo,fourcc) },
{ MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, MATROSKA_VIDEO_STEREOMODE_MONO, offsetof(MatroskaTrackVideo,stereoMode) },
{ MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE },
{ MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE },
{ MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE },
{ MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE },
{ MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE },
{ MATROSKA_ID_VIDEOFLAGINTERLACED,EBML_NONE },
{ MATROSKA_ID_VIDEOSTEREOMODE, EBML_NONE },
{ MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE },
{ 0 }
};
......@@ -329,6 +341,22 @@ static EbmlSyntax matroska_track_encodings[] = {
{ 0 }
};
static EbmlSyntax matroska_track_plane[] = {
{ MATROSKA_ID_TRACKPLANEUID, EBML_UINT, 0, offsetof(MatroskaTrackPlane,uid) },
{ MATROSKA_ID_TRACKPLANETYPE, EBML_UINT, 0, offsetof(MatroskaTrackPlane,type) },
{ 0 }
};
static EbmlSyntax matroska_track_combine_planes[] = {
{ MATROSKA_ID_TRACKPLANE, EBML_NEST, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n=matroska_track_plane} },
{ 0 }
};
static EbmlSyntax matroska_track_operation[] = {
{ MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, {.n=matroska_track_combine_planes} },
{ 0 }
};
static EbmlSyntax matroska_track[] = {
{ MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack,num) },
{ MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack,name) },
......@@ -343,6 +371,7 @@ static EbmlSyntax matroska_track[] = {
{ MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, offsetof(MatroskaTrack,flag_forced), {.u=0} },
{ MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, offsetof(MatroskaTrack,video), {.n=matroska_track_video} },
{ MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, offsetof(MatroskaTrack,audio), {.n=matroska_track_audio} },
{ MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack,operation), {.n=matroska_track_operation} },
{ MATROSKA_ID_TRACKCONTENTENCODINGS,EBML_NEST, 0, 0, {.n=matroska_track_encodings} },
{ MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE },
{ MATROSKA_ID_TRACKFLAGLACING, EBML_NONE },
......@@ -1196,6 +1225,9 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
EbmlList *chapters_list = &matroska->chapters;
MatroskaChapter *chapters;
MatroskaTrack *tracks;
EbmlList *combined_list;
MatroskaTrackPlane *planes;
char stereo_str[256];
EbmlList *index_list;
MatroskaIndex *index;
int index_scale = 1;
......@@ -1209,13 +1241,18 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
/* First read the EBML header. */
if (ebml_parse(matroska, ebml_syntax, &ebml)
|| ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t)
|| ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 2) {
|| ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 3) {
av_log(matroska->ctx, AV_LOG_ERROR,
"EBML header using unsupported features\n"
"(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
ebml.version, ebml.doctype, ebml.doctype_version);
ebml_free(ebml_syntax, &ebml);
return AVERROR_PATCHWELCOME;
} else if (ebml.doctype_version == 3) {
av_log(matroska->ctx, AV_LOG_WARNING,
"EBML header using unsupported features\n"
"(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
ebml.version, ebml.doctype, ebml.doctype_version);
}
for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++)
if (!strcmp(ebml.doctype, matroska_doctypes[i]))
......@@ -1475,6 +1512,86 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->need_parsing = AVSTREAM_PARSE_HEADERS;
if (track->default_duration)
st->avg_frame_rate = av_d2q(1000000000.0/track->default_duration, INT_MAX);
/* restore stereo mode flag as metadata tag */
switch (track->video.stereoMode) {
case MATROSKA_VIDEO_STEREOMODE_LEFT_RIGHT:
av_metadata_set2(&st->metadata, "STEREO_MODE", "left_right", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_BOTTOM_TOP:
av_metadata_set2(&st->metadata, "STEREO_MODE", "bottom_top", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_TOP_BOTTOM:
av_metadata_set2(&st->metadata, "STEREO_MODE", "top_bottom", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_CHECKERBOARD_RL:
av_metadata_set2(&st->metadata, "STEREO_MODE", "checkerboard_rl", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_CHECKERBOARD_LR:
av_metadata_set2(&st->metadata, "STEREO_MODE", "checkerboard_lr", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_ROW_INTERLEAVED_RL:
av_metadata_set2(&st->metadata, "STEREO_MODE", "row_interleaved_rl", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_ROW_INTERLEAVED_LR:
av_metadata_set2(&st->metadata, "STEREO_MODE", "row_interleaved_lr", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_COL_INTERLEAVED_RL:
av_metadata_set2(&st->metadata, "STEREO_MODE", "col_interleaved_rl", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_COL_INTERLEAVED_LR:
av_metadata_set2(&st->metadata, "STEREO_MODE", "col_interleaved_lr", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_ANAGLYPH_CYAN_RED:
av_metadata_set2(&st->metadata, "STEREO_MODE", "anaglyph_cyan_red", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_RIGHT_LEFT:
av_metadata_set2(&st->metadata, "STEREO_MODE", "right_left", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_ANAGLYPH_GREEN_MAG:
av_metadata_set2(&st->metadata, "STEREO_MODE", "anaglyph_green_magenta", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_LR:
av_metadata_set2(&st->metadata, "STEREO_MODE", "block_lr", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_RL:
av_metadata_set2(&st->metadata, "STEREO_MODE", "block_rl", 0);
break;
case MATROSKA_VIDEO_STEREOMODE_MONO:
default:
/**av_metadata_set2(&st->metadata, "STEREO_MODE", "mono", 0);*/
break;
}
/* if we have virtual track - mark the real tracks */
combined_list = &track->operation.combine_planes;
planes = combined_list->elem;
for (int plane_id = 0; plane_id < combined_list->nb_elem; ++plane_id) {
switch (planes[plane_id].type) {
case 0: {
snprintf(stereo_str, sizeof(stereo_str), "left_%d", i);
break;
}
case 1: {
snprintf(stereo_str, sizeof(stereo_str), "right_%d", i);
break;
}
case 2: {
snprintf(stereo_str, sizeof(stereo_str), "background_%d", i);
break;
}
default: {
continue;
}
}
for (int track_id = 0; track_id < matroska->tracks.nb_elem && track_id < i; ++track_id) {
MatroskaTrack *check_track = &tracks[track_id];
if (planes[plane_id].uid == check_track->uid) {
av_metadata_set2(&s->streams[track_id]->metadata, "STEREO_MODE", stereo_str, 0);
break;
}
}
}
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
st->codec->sample_rate = track->audio.out_samplerate;
......
......@@ -586,10 +586,45 @@ static int mkv_write_tracks(AVFormatContext *s)
// XXX: interlace flag?
put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
if ((tag = av_metadata_get(s->metadata, "stereo_mode", NULL, 0))) {
uint8_t stereo_fmt = atoi(tag->value);
if ((tag = av_metadata_get(st->metadata, "STEREO_MODE", NULL, 0)) ||
(tag = av_metadata_get( s->metadata, "STEREO_MODE", NULL, 0))) {
// save stereomode flag
uint64_t stereo_fmt = -1;
int valid_fmt = 0;
if (!strcmp(tag->value, "mono")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_MONO;
} else if (!strcmp(tag->value, "left_right")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_LEFT_RIGHT;
} else if (!strcmp(tag->value, "bottom_top")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_BOTTOM_TOP;
} else if (!strcmp(tag->value, "top_bottom")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_TOP_BOTTOM;
} else if (!strcmp(tag->value, "checkerboard_rl")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_CHECKERBOARD_RL;
} else if (!strcmp(tag->value, "checkerboard_lr")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_CHECKERBOARD_LR;
} else if (!strcmp(tag->value, "row_interleaved_rl")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_ROW_INTERLEAVED_RL;
} else if (!strcmp(tag->value, "row_interleaved_lr")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_ROW_INTERLEAVED_LR;
} else if (!strcmp(tag->value, "col_interleaved_rl")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_COL_INTERLEAVED_RL;
} else if (!strcmp(tag->value, "col_interleaved_lr")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_COL_INTERLEAVED_LR;
} else if (!strcmp(tag->value, "anaglyph_cyan_red")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_ANAGLYPH_CYAN_RED;
} else if (!strcmp(tag->value, "right_left")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_RIGHT_LEFT;
} else if (!strcmp(tag->value, "anaglyph_green_magenta")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_ANAGLYPH_GREEN_MAG;
} else if (!strcmp(tag->value, "block_lr")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_LR;
} else if (!strcmp(tag->value, "block_rl")) {
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_RL;
}
switch (mkv->mode) {
case MODE_WEBM:
if (stereo_fmt <= MATROSKA_VIDEO_STEREOMODE_TOP_BOTTOM
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment