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;