matroska: cleanup handling of video stereo mode
authorAurelien Jacobs <aurel@gnuage.org>
Mon, 23 May 2011 23:09:24 +0000 (01:09 +0200)
committerAurelien Jacobs <aurel@gnuage.org>
Mon, 23 May 2011 23:12:19 +0000 (01:12 +0200)
doc/muxers.texi
libavformat/matroska.c
libavformat/matroska.h
libavformat/matroskadec.c
libavformat/matroskaenc.c

index 03be693..55b44d1 100644 (file)
@@ -232,7 +232,7 @@ Specifies the language of the track in the Matroska languages form
 
 @table @option
 
-@item STEREO_MODE=@var{mode}
+@item stereo_mode=@var{mode}
 Stereo 3D video layout of two views in a single video track
 @table @option
 @item mono
@@ -270,7 +270,7 @@ Both eyes laced in one Block, Right-eye view is first
 
 For example a 3D WebM clip can be created using the following command line:
 @example
-ffmpeg -i sample_left_right_clip.mpg -an -vcodec libvpx -metadata STEREO_MODE=left_right -y stereo_clip.webm
+ffmpeg -i sample_left_right_clip.mpg -an -vcodec libvpx -metadata stereo_mode=left_right -y stereo_clip.webm
 @end example
 
 @c man end MUXERS
index c7e9663..fe9b042 100644 (file)
@@ -99,3 +99,27 @@ const AVMetadataConv ff_mkv_metadata_conv[] = {
     { "PART_NUMBER"   , "track"  },
     { 0 }
 };
+
+const char const *matroska_video_stereo_mode[] = {
+    "mono",
+    "left_right",
+    "bottom_top",
+    "top_bottom",
+    "checkerboard_rl",
+    "checkerboard_lr"
+    "row_interleaved_rl",
+    "row_interleaved_lr",
+    "col_interleaved_rl",
+    "col_interleaved_lr",
+    "anaglyph_cyan_red",
+    "right_left",
+    "anaglyph_green_magenta",
+    "block_lr",
+    "block_rl",
+};
+
+const char const *matroska_video_stereo_plane[] = {
+    "left",
+    "right",
+    "background",
+};
index 4895977..949195b 100644 (file)
@@ -223,24 +223,6 @@ typedef enum {
   MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP = 3,
 } MatroskaTrackEncodingCompAlgo;
 
-typedef enum {
-  MATROSKA_VIDEO_STEREOMODE_MONO               = 0,
-  MATROSKA_VIDEO_STEREOMODE_LEFT_RIGHT         = 1,
-  MATROSKA_VIDEO_STEREOMODE_BOTTOM_TOP         = 2,
-  MATROSKA_VIDEO_STEREOMODE_TOP_BOTTOM         = 3,
-  MATROSKA_VIDEO_STEREOMODE_CHECKERBOARD_RL    = 4,
-  MATROSKA_VIDEO_STEREOMODE_CHECKERBOARD_LR    = 5,
-  MATROSKA_VIDEO_STEREOMODE_ROW_INTERLEAVED_RL = 6,
-  MATROSKA_VIDEO_STEREOMODE_ROW_INTERLEAVED_LR = 7,
-  MATROSKA_VIDEO_STEREOMODE_COL_INTERLEAVED_RL = 8,
-  MATROSKA_VIDEO_STEREOMODE_COL_INTERLEAVED_LR = 9,
-  MATROSKA_VIDEO_STEREOMODE_ANAGLYPH_CYAN_RED  = 10,
-  MATROSKA_VIDEO_STEREOMODE_RIGHT_LEFT         = 11,
-  MATROSKA_VIDEO_STEREOMODE_ANAGLYPH_GREEN_MAG = 12,
-  MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_LR = 13,
-  MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_RL = 14,
-} MatroskaVideoStereoModeType;
-
 /*
  * Matroska Codec IDs, strings
  */
@@ -261,5 +243,10 @@ typedef struct CodecMime{
 extern const CodecTags ff_mkv_codec_tags[];
 extern const CodecMime ff_mkv_mime_tags[];
 extern const AVMetadataConv ff_mkv_metadata_conv[];
+extern const char const *matroska_video_stereo_mode[];
+extern const char const *matroska_video_stereo_plane[];
+
+#define MATROSKA_VIDEO_STEREO_MODE_COUNT  15
+#define MATROSKA_VIDEO_STEREO_PLANE_COUNT  3
 
 #endif /* AVFORMAT_MATROSKA_H */
index 90623bf..eca3277 100644 (file)
@@ -112,7 +112,7 @@ typedef struct {
     uint64_t pixel_width;
     uint64_t pixel_height;
     uint64_t fourcc;
-    uint64_t stereoMode;
+    uint64_t stereo_mode;
 } MatroskaTrackVideo;
 
 typedef struct {
@@ -139,7 +139,6 @@ typedef struct {
 
 typedef struct {
     EbmlList combine_planes;
-    /*EbmlList join_blocks;*/
 } MatroskaTrackOperation;
 
 typedef struct {
@@ -303,7 +302,7 @@ 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_VIDEOSTEREOMODE,    EBML_UINT, 0, offsetof(MatroskaTrackVideo,stereo_mode) },
     { MATROSKA_ID_VIDEOPIXELCROPB,    EBML_NONE },
     { MATROSKA_ID_VIDEOPIXELCROPT,    EBML_NONE },
     { MATROSKA_ID_VIDEOPIXELCROPL,    EBML_NONE },
@@ -1225,16 +1224,13 @@ 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;
     uint64_t max_start = 0;
     Ebml ebml = { 0 };
     AVStream *st;
-    int i, j, res;
+    int i, j, k, res;
 
     matroska->ctx = s;
 
@@ -1499,6 +1495,8 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
         }
 
         if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
+            MatroskaTrackPlane *planes = track->operation.combine_planes.elem;
+
             st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
             st->codec->codec_tag  = track->video.fourcc;
             st->codec->width  = track->video.pixel_width;
@@ -1513,84 +1511,23 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
             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);
+            /* export stereo mode flag as metadata tag */
+            if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREO_MODE_COUNT)
+                av_metadata_set2(&st->metadata, "stereo_mode", matroska_video_stereo_mode[track->video.stereo_mode], 0);
+
+            /* if we have virtual track, mark the real tracks */
+            for (j=0; j < track->operation.combine_planes.nb_elem; j++) {
+                char buf[32];
+                if (planes[j].type < MATROSKA_VIDEO_STEREO_PLANE_COUNT)
+                    continue;
+                snprintf(buf, sizeof(buf), "%s_%d",
+                         matroska_video_stereo_plane[planes[j].type], i);
+                for (k=0; k < matroska->tracks.nb_elem; k++)
+                    if (planes[j].uid == tracks[k].uid) {
+                        av_metadata_set2(&s->streams[k]->metadata,
+                                         "stereo_mode", buf, 0);
                         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;
index 0fe760b..c3e203c 100644 (file)
@@ -587,58 +587,24 @@ static int mkv_write_tracks(AVFormatContext *s)
                 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
                 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
 
-                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
-                             || stereo_fmt == MATROSKA_VIDEO_STEREOMODE_RIGHT_LEFT)
-                            valid_fmt = 1;
+                if ((tag = av_metadata_get(st->metadata, "stereo_mode", NULL, 0)) ||
+                    (tag = av_metadata_get( s->metadata, "stereo_mode", NULL, 0))) {
+                    // save stereo mode flag
+                    uint64_t st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT;
+
+                    for (j=0; j<MATROSKA_VIDEO_STEREO_MODE_COUNT; j++)
+                        if (!strcmp(tag->value, matroska_video_stereo_mode[j])){
+                            st_mode = j;
                             break;
-                        case MODE_MATROSKAv2:
-                            if (stereo_fmt <= MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_RL)
-                                valid_fmt = 1;
-                            break;
-                    }
-
-                    if (valid_fmt)
-                        put_ebml_uint (pb, MATROSKA_ID_VIDEOSTEREOMODE, stereo_fmt);
+                        }
+
+                    if ((mkv->mode == MODE_WEBM && st_mode > 3 && st_mode != 11)
+                        || st_mode >= MATROSKA_VIDEO_STEREO_MODE_COUNT) {
+                        av_log(s, AV_LOG_ERROR,
+                               "The specified stereo mode is not valid.\n");
+                        return AVERROR(EINVAL);
+                    } else
+                        put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode);
                 }
 
                 if (st->sample_aspect_ratio.num) {
@@ -786,7 +752,7 @@ static int mkv_write_tag(AVFormatContext *s, AVMetadata *m, unsigned int element
     end_ebml_master(s->pb, targets);
 
     while ((t = av_metadata_get(m, "", t, AV_METADATA_IGNORE_SUFFIX)))
-        if (strcasecmp(t->key, "title"))
+        if (strcasecmp(t->key, "title") && strcasecmp(t->key, "stereo_mode"))
             mkv_write_simpletag(s->pb, t);
 
     end_ebml_master(s->pb, tag);