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:
parent
2ef241c09f
commit
4c509fe305
@ -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
|
||||
|
@ -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",
|
||||
};
|
||||
|
@ -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 */
|
||||
|
@ -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,85 +1511,24 @@ 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);
|
||||
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: {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
|
||||
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
st->codec->sample_rate = track->audio.out_samplerate;
|
||||
|
@ -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;
|
||||
break;
|
||||
case MODE_MATROSKAv2:
|
||||
if (stereo_fmt <= MATROSKA_VIDEO_STEREOMODE_BOTH_EYES_BLOCK_RL)
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user