Merge commit 'bae05e5326703dad3bfe0ed5b31ba73ee9254515' into release/2.4
authorMichael Niedermayer <michaelni@gmx.at>
Sun, 18 Jan 2015 00:33:20 +0000 (01:33 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 18 Jan 2015 00:33:33 +0000 (01:33 +0100)
* commit 'bae05e5326703dad3bfe0ed5b31ba73ee9254515':
  matroskaenc: write correct Display{Width, Height} in stereo encoding

Conflicts:
libavformat/matroskaenc.c

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

@@@ -694,26 -625,19 +694,28 @@@ static int mkv_write_codecprivate(AVFor
      return ret;
  }
  
 +
  static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb,
--                                 AVStream *st, int mode)
++                                 AVStream *st, int mode, int *h_width, int *h_height)
  {
      int i;
 -    int display_width, display_height;
 -    int h_width = 1, h_height = 1;
 -    AVCodecContext *codec = st->codec;
 +    int ret = 0;
      AVDictionaryEntry *tag;
      MatroskaVideoStereoModeType format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB;
  
++    *h_width = 1;
++    *h_height = 1;
      // 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_STEREOMODE_TYPE_NB; 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);
                  format = (stereo->flags & AV_STEREO3D_FLAG_INVERT)
                      ? MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT
                      : MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT;
 -                h_width = 2;
++                *h_width = 2;
                  break;
              case AV_STEREO3D_TOPBOTTOM:
                  format = MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM;
                  if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
                      format--;
 -                h_height = 2;
++                *h_height = 2;
                  break;
              case AV_STEREO3D_CHECKERBOARD:
                  format = MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR;
                  format = MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR;
                  if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
                      format--;
 -                h_height = 2;
++                *h_height = 2;
                  break;
              case AV_STEREO3D_COLUMNS:
                  format = MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR;
                  if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
                      format--;
 -                h_width = 2;
++                *h_width = 2;
                  break;
              case AV_STEREO3D_FRAMESEQUENCE:
                  format = MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR;
                      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 webm, do not write unsupported modes
 +    if ((mode == MODE_WEBM &&
 +        format > MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM &&
 +        format != MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT)
 +        || format >= MATROSKA_VIDEO_STEREOMODE_TYPE_NB) {
 +        av_log(s, AV_LOG_ERROR,
 +               "The specified stereo mode is not valid.\n");
          format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB;
 +        return AVERROR(EINVAL);
 +    }
  
 -    if (format < MATROSKA_VIDEO_STEREOMODE_TYPE_NB)
 -        put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, format);
 -
 -    // write DisplayWidth and DisplayHeight, they contain the size of
 -    // a single source view and/or the display aspect ratio
 -    display_width  = codec->width  / h_width;
 -    display_height = codec->height / h_height;
 -    if (st->sample_aspect_ratio.num) {
 -        display_width *= av_q2d(st->sample_aspect_ratio);
 -        put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, 3); // DAR
 -    }
 -    if (st->sample_aspect_ratio.num ||
 -        format < MATROSKA_VIDEO_STEREOMODE_TYPE_NB) {
 -        put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH,  display_width);
 -        put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, display_height);
 -    }
+     // write StereoMode if format is valid
 +    put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, format);
  
 -    return 0;
 +    return ret;
  }
  
  static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
  
          // 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);
++        ret = mkv_write_stereo_mode(s, pb, st, mkv->mode,
++                                    &display_width_div,
++                                    &display_height_div);
          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);
 +        }
 +
++        // write DisplayWidth and DisplayHeight, they contain the size of
++        // a single source view and/or the display aspect ratio
 +        if (st->sample_aspect_ratio.num) {
 +            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;