|
|
@@ -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; |
|
|
|