1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

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 @table @option
@item STEREO_MODE=@var{mode} @item stereo_mode=@var{mode}
Stereo 3D video layout of two views in a single video track Stereo 3D video layout of two views in a single video track
@table @option @table @option
@item mono @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: For example a 3D WebM clip can be created using the following command line:
@example @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 @end example
@c man end MUXERS @c man end MUXERS

View File

@ -99,3 +99,27 @@ const AVMetadataConv ff_mkv_metadata_conv[] = {
{ "PART_NUMBER" , "track" }, { "PART_NUMBER" , "track" },
{ 0 } { 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, MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP = 3,
} MatroskaTrackEncodingCompAlgo; } 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 * Matroska Codec IDs, strings
*/ */
@ -261,5 +243,10 @@ typedef struct CodecMime{
extern const CodecTags ff_mkv_codec_tags[]; extern const CodecTags ff_mkv_codec_tags[];
extern const CodecMime ff_mkv_mime_tags[]; extern const CodecMime ff_mkv_mime_tags[];
extern const AVMetadataConv ff_mkv_metadata_conv[]; 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 */ #endif /* AVFORMAT_MATROSKA_H */

View File

@ -112,7 +112,7 @@ typedef struct {
uint64_t pixel_width; uint64_t pixel_width;
uint64_t pixel_height; uint64_t pixel_height;
uint64_t fourcc; uint64_t fourcc;
uint64_t stereoMode; uint64_t stereo_mode;
} MatroskaTrackVideo; } MatroskaTrackVideo;
typedef struct { typedef struct {
@ -139,7 +139,6 @@ typedef struct {
typedef struct { typedef struct {
EbmlList combine_planes; EbmlList combine_planes;
/*EbmlList join_blocks;*/
} MatroskaTrackOperation; } MatroskaTrackOperation;
typedef struct { typedef struct {
@ -303,7 +302,7 @@ static EbmlSyntax matroska_track_video[] = {
{ MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_width) }, { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_width) },
{ MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_height) }, { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_height) },
{ MATROSKA_ID_VIDEOCOLORSPACE, EBML_UINT, 0, offsetof(MatroskaTrackVideo,fourcc) }, { 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_VIDEOPIXELCROPB, EBML_NONE },
{ MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE },
{ MATROSKA_ID_VIDEOPIXELCROPL, 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; EbmlList *chapters_list = &matroska->chapters;
MatroskaChapter *chapters; MatroskaChapter *chapters;
MatroskaTrack *tracks; MatroskaTrack *tracks;
EbmlList *combined_list;
MatroskaTrackPlane *planes;
char stereo_str[256];
EbmlList *index_list; EbmlList *index_list;
MatroskaIndex *index; MatroskaIndex *index;
int index_scale = 1; int index_scale = 1;
uint64_t max_start = 0; uint64_t max_start = 0;
Ebml ebml = { 0 }; Ebml ebml = { 0 };
AVStream *st; AVStream *st;
int i, j, res; int i, j, k, res;
matroska->ctx = s; matroska->ctx = s;
@ -1499,6 +1495,8 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
} }
if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
MatroskaTrackPlane *planes = track->operation.combine_planes.elem;
st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
st->codec->codec_tag = track->video.fourcc; st->codec->codec_tag = track->video.fourcc;
st->codec->width = track->video.pixel_width; st->codec->width = track->video.pixel_width;
@ -1513,85 +1511,24 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
if (track->default_duration) if (track->default_duration)
st->avg_frame_rate = av_d2q(1000000000.0/track->default_duration, INT_MAX); st->avg_frame_rate = av_d2q(1000000000.0/track->default_duration, INT_MAX);
/* restore stereo mode flag as metadata tag */ /* export stereo mode flag as metadata tag */
switch (track->video.stereoMode) { if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREO_MODE_COUNT)
case MATROSKA_VIDEO_STEREOMODE_LEFT_RIGHT: av_metadata_set2(&st->metadata, "stereo_mode", matroska_video_stereo_mode[track->video.stereo_mode], 0);
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 */ /* if we have virtual track, mark the real tracks */
combined_list = &track->operation.combine_planes; for (j=0; j < track->operation.combine_planes.nb_elem; j++) {
planes = combined_list->elem; char buf[32];
for (int plane_id = 0; plane_id < combined_list->nb_elem; ++plane_id) { if (planes[j].type < MATROSKA_VIDEO_STEREO_PLANE_COUNT)
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);
break;
}
default: {
continue; continue;
} snprintf(buf, sizeof(buf), "%s_%d",
} matroska_video_stereo_plane[planes[j].type], i);
for (int track_id = 0; track_id < matroska->tracks.nb_elem && track_id < i; ++track_id) { for (k=0; k < matroska->tracks.nb_elem; k++)
MatroskaTrack *check_track = &tracks[track_id]; if (planes[j].uid == tracks[k].uid) {
if (planes[plane_id].uid == check_track->uid) { av_metadata_set2(&s->streams[k]->metadata,
av_metadata_set2(&s->streams[track_id]->metadata, "STEREO_MODE", stereo_str, 0); "stereo_mode", buf, 0);
break; break;
} }
} }
}
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
st->codec->sample_rate = track->audio.out_samplerate; st->codec->sample_rate = track->audio.out_samplerate;

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_VIDEOPIXELWIDTH , codec->width);
put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
if ((tag = av_metadata_get(st->metadata, "STEREO_MODE", NULL, 0)) || if ((tag = av_metadata_get(st->metadata, "stereo_mode", NULL, 0)) ||
(tag = av_metadata_get( s->metadata, "STEREO_MODE", NULL, 0))) { (tag = av_metadata_get( s->metadata, "stereo_mode", NULL, 0))) {
// save stereomode flag // save stereo mode flag
uint64_t stereo_fmt = -1; uint64_t st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT;
int valid_fmt = 0;
if (!strcmp(tag->value, "mono")) { for (j=0; j<MATROSKA_VIDEO_STEREO_MODE_COUNT; j++)
stereo_fmt = MATROSKA_VIDEO_STEREOMODE_MONO; if (!strcmp(tag->value, matroska_video_stereo_mode[j])){
} else if (!strcmp(tag->value, "left_right")) { st_mode = j;
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;
break;
case MODE_MATROSKAv2:
if (stereo_fmt <= MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_RL)
valid_fmt = 1;
break; break;
} }
if (valid_fmt) if ((mkv->mode == MODE_WEBM && st_mode > 3 && st_mode != 11)
put_ebml_uint (pb, MATROSKA_ID_VIDEOSTEREOMODE, stereo_fmt); || 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) { 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); end_ebml_master(s->pb, targets);
while ((t = av_metadata_get(m, "", t, AV_METADATA_IGNORE_SUFFIX))) 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); mkv_write_simpletag(s->pb, t);
end_ebml_master(s->pb, tag); end_ebml_master(s->pb, tag);