Merge commit '4d686fb721b485ebbc4c7779d927d876c1e630f7'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 28 Aug 2014 22:30:47 +0000 (00:30 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 28 Aug 2014 22:44:47 +0000 (00:44 +0200)
* commit '4d686fb721b485ebbc4c7779d927d876c1e630f7':
  matroskaenc: convert avstream stereo3d side data during encoding

Conflicts:
libavformat/matroskaenc.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavformat/matroskaenc.c

@@@ -45,7 -43,7 +45,8 @@@
  #include "libavutil/opt.h"
  #include "libavutil/random_seed.h"
  #include "libavutil/samplefmt.h"
 +#include "libavutil/sha.h"
+ #include "libavutil/stereo3d.h"
  
  #include "libavcodec/xiph.h"
  #include "libavcodec/mpeg4audio.h"
@@@ -693,18 -625,78 +694,96 @@@ static int mkv_write_codecprivate(AVFor
      return ret;
  }
  
- static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, int st_mode,
-                                   int mode)
++
+ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb,
+                                  AVStream *st, int mode)
  {
-     if ((mode == MODE_WEBM && st_mode > 3 && st_mode != 11)
-         || st_mode >= MATROSKA_VIDEO_STEREO_MODE_COUNT) {
+     int i;
++    int ret = 0;
+     AVDictionaryEntry *tag;
+     MatroskaVideoStereoModeType format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB;
+     // convert metadata into proper side data and add it to the stream
 -    if ((tag = av_dict_get(s->metadata, "stereo_mode", NULL, 0))) {
++    if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) ||
++        (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) {
+         int stereo_mode = atoi(tag->value);
++
++        for (i=0; i<MATROSKA_VIDEO_STEREO_MODE_COUNT; i++)
++            if (!strcmp(tag->value, ff_matroska_video_stereo_mode[i])){
++                stereo_mode = i;
++                break;
++            }
++
+         if (stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB &&
+             stereo_mode != 10 && stereo_mode != 12) {
+             int ret = ff_mkv_stereo3d_conv(st, stereo_mode);
+             if (ret < 0)
+                 return ret;
+         }
+     }
+     for (i = 0; i < st->nb_side_data; i++) {
+         AVPacketSideData sd = st->side_data[i];
+         if (sd.type == AV_PKT_DATA_STEREO3D) {
+             AVStereo3D *stereo = (AVStereo3D *)sd.data;
+             switch (stereo->type) {
+             case AV_STEREO3D_2D:
+                 format = MATROSKA_VIDEO_STEREOMODE_TYPE_MONO;
+                 break;
+             case AV_STEREO3D_SIDEBYSIDE:
+                 format = (stereo->flags & AV_STEREO3D_FLAG_INVERT)
+                     ? MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT
+                     : MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT;
+                 break;
+             case AV_STEREO3D_TOPBOTTOM:
+                 format = MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM;
+                 if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
+                     format--;
+                 break;
+             case AV_STEREO3D_CHECKERBOARD:
+                 format = MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR;
+                 if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
+                     format--;
+                 break;
+             case AV_STEREO3D_LINES:
+                 format = MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR;
+                 if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
+                     format--;
+                 break;
+             case AV_STEREO3D_COLUMNS:
+                 format = MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR;
+                 if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
+                     format--;
+                 break;
+             case AV_STEREO3D_FRAMESEQUENCE:
+                 format = MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR;
+                 if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
+                     format++;
+                 break;
+             }
++            ret = stereo->type;
+             break;
+         }
+     }
 -    if (mode == MODE_WEBM &&
 -        (format > MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM &&
 -         format != MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT))
++    if (format == MATROSKA_VIDEO_STEREOMODE_TYPE_NB)
++        return ret;
++
++    if ((mode == MODE_WEBM &&
++        format > MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM &&
++        format != MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT)
++        || format >= MATROSKA_VIDEO_STEREO_MODE_COUNT) {
 +        av_log(s, AV_LOG_ERROR,
 +               "The specified stereo mode is not valid.\n");
+         format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB;
 +        return AVERROR(EINVAL);
-     } else
-         put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode);
++    }
  
-     return 0;
 -    if (format < MATROSKA_VIDEO_STEREOMODE_TYPE_NB)
 -        put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, format);
++    put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, format);
 -    return 0;
++    return ret;
  }
  
  static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
          put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
          put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
  
-         if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) ||
-             (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) {
-             int st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT;
-             for (j=0; j<MATROSKA_VIDEO_STEREO_MODE_COUNT; j++)
-                 if (!strcmp(tag->value, ff_matroska_video_stereo_mode[j])){
-                     st_mode = j;
-                     break;
-                 }
-             if (mkv_write_stereo_mode(s, pb, st_mode, mkv->mode) < 0)
-                 return AVERROR(EINVAL);
-             switch (st_mode) {
-             case 1:
-             case 8:
-             case 9:
-             case 11:
-                 display_width_div = 2;
-                 break;
-             case 2:
-             case 3:
-             case 6:
-             case 7:
-                 display_height_div = 2;
-                 break;
-             }
+         // check both side data and metadata for stereo information,
+         // write the result to the bitstream if any is found
+         ret = mkv_write_stereo_mode(s, pb, st, mkv->mode);
+         if (ret < 0)
+             return ret;
++        switch (ret) {
++        case AV_STEREO3D_SIDEBYSIDE:
++        case AV_STEREO3D_COLUMNS:
++            display_width_div = 2;
++            break;
++        case AV_STEREO3D_TOPBOTTOM:
++        case AV_STEREO3D_LINES:
++            display_height_div = 2;
++            break;
 +        }
 +
 +        if (((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) ||
 +            ((tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) ||
 +            (codec->pix_fmt == AV_PIX_FMT_YUVA420P)) {
 +            put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1);
 +        }
 +
          if (st->sample_aspect_ratio.num) {
 -            int d_width = codec->width*av_q2d(st->sample_aspect_ratio);
 -            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width);
 -            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height);
 -            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, 3);
 +            int64_t d_width = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
 +            if (d_width > INT_MAX) {
 +                av_log(s, AV_LOG_ERROR, "Overflow in display width\n");
 +                return AVERROR(EINVAL);
 +            }
 +            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div);
 +            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);
 +        } else if (display_width_div != 1 || display_height_div != 1) {
 +            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->width / display_width_div);
 +            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);
 +        }
 +
 +        if (codec->codec_id == AV_CODEC_ID_RAWVIDEO) {
 +            uint32_t color_space = av_le2ne32(codec->codec_tag);
 +            put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space));
          }
          end_ebml_master(pb, subinfo);
          break;