mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
matroska: switch stereo mode from int to string and add support in the demuxer too
This commit is contained in:
parent
69a83da5d4
commit
e6ec9212c5
@ -79,6 +79,11 @@
|
||||
#define MATROSKA_ID_TRACKTYPE 0x83
|
||||
#define MATROSKA_ID_TRACKVIDEO 0xE0
|
||||
#define MATROSKA_ID_TRACKAUDIO 0xE1
|
||||
#define MATROSKA_ID_TRACKOPERATION 0xE2
|
||||
#define MATROSKA_ID_TRACKCOMBINEPLANES 0xE3
|
||||
#define MATROSKA_ID_TRACKPLANE 0xE4
|
||||
#define MATROSKA_ID_TRACKPLANEUID 0xE5
|
||||
#define MATROSKA_ID_TRACKPLANETYPE 0xE6
|
||||
#define MATROSKA_ID_CODECID 0x86
|
||||
#define MATROSKA_ID_CODECPRIVATE 0x63A2
|
||||
#define MATROSKA_ID_CODECNAME 0x258688
|
||||
|
@ -112,6 +112,7 @@ typedef struct {
|
||||
uint64_t pixel_width;
|
||||
uint64_t pixel_height;
|
||||
uint64_t fourcc;
|
||||
uint64_t stereoMode;
|
||||
} MatroskaTrackVideo;
|
||||
|
||||
typedef struct {
|
||||
@ -131,6 +132,16 @@ typedef struct {
|
||||
uint8_t *buf;
|
||||
} MatroskaTrackAudio;
|
||||
|
||||
typedef struct {
|
||||
uint64_t uid;
|
||||
uint64_t type;
|
||||
} MatroskaTrackPlane;
|
||||
|
||||
typedef struct {
|
||||
EbmlList combine_planes;
|
||||
/*EbmlList join_blocks;*/
|
||||
} MatroskaTrackOperation;
|
||||
|
||||
typedef struct {
|
||||
uint64_t num;
|
||||
uint64_t uid;
|
||||
@ -145,6 +156,7 @@ typedef struct {
|
||||
uint64_t flag_forced;
|
||||
MatroskaTrackVideo video;
|
||||
MatroskaTrackAudio audio;
|
||||
MatroskaTrackOperation operation;
|
||||
EbmlList encodings;
|
||||
|
||||
AVStream *stream;
|
||||
@ -291,13 +303,13 @@ 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_VIDEOPIXELCROPB, EBML_NONE },
|
||||
{ MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE },
|
||||
{ MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE },
|
||||
{ MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE },
|
||||
{ MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE },
|
||||
{ MATROSKA_ID_VIDEOFLAGINTERLACED,EBML_NONE },
|
||||
{ MATROSKA_ID_VIDEOSTEREOMODE, EBML_NONE },
|
||||
{ MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE },
|
||||
{ 0 }
|
||||
};
|
||||
@ -329,6 +341,22 @@ static EbmlSyntax matroska_track_encodings[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static EbmlSyntax matroska_track_plane[] = {
|
||||
{ MATROSKA_ID_TRACKPLANEUID, EBML_UINT, 0, offsetof(MatroskaTrackPlane,uid) },
|
||||
{ MATROSKA_ID_TRACKPLANETYPE, EBML_UINT, 0, offsetof(MatroskaTrackPlane,type) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static EbmlSyntax matroska_track_combine_planes[] = {
|
||||
{ MATROSKA_ID_TRACKPLANE, EBML_NEST, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n=matroska_track_plane} },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static EbmlSyntax matroska_track_operation[] = {
|
||||
{ MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, {.n=matroska_track_combine_planes} },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static EbmlSyntax matroska_track[] = {
|
||||
{ MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack,num) },
|
||||
{ MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack,name) },
|
||||
@ -343,6 +371,7 @@ static EbmlSyntax matroska_track[] = {
|
||||
{ MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, offsetof(MatroskaTrack,flag_forced), {.u=0} },
|
||||
{ MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, offsetof(MatroskaTrack,video), {.n=matroska_track_video} },
|
||||
{ MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, offsetof(MatroskaTrack,audio), {.n=matroska_track_audio} },
|
||||
{ MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack,operation), {.n=matroska_track_operation} },
|
||||
{ MATROSKA_ID_TRACKCONTENTENCODINGS,EBML_NEST, 0, 0, {.n=matroska_track_encodings} },
|
||||
{ MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE },
|
||||
{ MATROSKA_ID_TRACKFLAGLACING, EBML_NONE },
|
||||
@ -1196,6 +1225,9 @@ 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;
|
||||
@ -1209,13 +1241,18 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
||||
/* First read the EBML header. */
|
||||
if (ebml_parse(matroska, ebml_syntax, &ebml)
|
||||
|| ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t)
|
||||
|| ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 2) {
|
||||
|| ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 3) {
|
||||
av_log(matroska->ctx, AV_LOG_ERROR,
|
||||
"EBML header using unsupported features\n"
|
||||
"(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
|
||||
ebml.version, ebml.doctype, ebml.doctype_version);
|
||||
ebml_free(ebml_syntax, &ebml);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
} else if (ebml.doctype_version == 3) {
|
||||
av_log(matroska->ctx, AV_LOG_WARNING,
|
||||
"EBML header using unsupported features\n"
|
||||
"(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
|
||||
ebml.version, ebml.doctype, ebml.doctype_version);
|
||||
}
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++)
|
||||
if (!strcmp(ebml.doctype, matroska_doctypes[i]))
|
||||
@ -1475,6 +1512,86 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
||||
st->need_parsing = AVSTREAM_PARSE_HEADERS;
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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: {
|
||||
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;
|
||||
st->codec->sample_rate = track->audio.out_samplerate;
|
||||
|
@ -586,10 +586,45 @@ static int mkv_write_tracks(AVFormatContext *s)
|
||||
// XXX: interlace flag?
|
||||
put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
|
||||
put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
|
||||
if ((tag = av_metadata_get(s->metadata, "stereo_mode", NULL, 0))) {
|
||||
uint8_t stereo_fmt = atoi(tag->value);
|
||||
|
||||
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 (!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
|
||||
|
Loading…
x
Reference in New Issue
Block a user