summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorKirill Gavrilov <gavr.mail@gmail.com>2011-05-21 17:14:14 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-05-21 17:23:30 +0200
commite6ec9212c543c77ab3ddab90ac52021cfbbdac17 (patch)
tree1ba4103f406b5cb0e8213d9b625f16ca0b7bad79 /libavformat
parent69a83da5d40833e20da07830eda8ecbc31735116 (diff)
matroska: switch stereo mode from int to string and add support in the demuxer too
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/matroska.h5
-rw-r--r--libavformat/matroskadec.c121
-rw-r--r--libavformat/matroskaenc.c39
3 files changed, 161 insertions, 4 deletions
diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index b112351529..48959772f1 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -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
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 8f9340dbdc..90623bf89f 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -112,6 +112,7 @@ typedef struct {
uint64_t pixel_width;
uint64_t pixel_height;
uint64_t fourcc;
+ uint64_t stereoMode;
} MatroskaTrackVideo;
typedef struct {
@@ -132,6 +133,16 @@ typedef struct {
} 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;
uint64_t type;
@@ -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;
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 564b7509c1..0fe760b684 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -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