matroska: cleanup handling of video stereo mode

This commit is contained in:
Aurelien Jacobs 2011-05-24 01:09:24 +02:00
parent 2ef241c09f
commit 4c509fe305
5 changed files with 66 additions and 152 deletions

View 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

View 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",
};

View 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 */

View 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;
}
/* 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 */
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);
/* 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;
}
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;

View 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 ((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;
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;
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);