[FFmpeg-cvslog] r14562 - trunk/libavformat/matroskadec.c
aurel
subversion
Tue Aug 5 02:40:31 CEST 2008
Author: aurel
Date: Tue Aug 5 02:40:31 2008
New Revision: 14562
Log:
matroskadec: use generic parser to parse tracks
Modified:
trunk/libavformat/matroskadec.c
Modified: trunk/libavformat/matroskadec.c
==============================================================================
--- trunk/libavformat/matroskadec.c (original)
+++ trunk/libavformat/matroskadec.c Tue Aug 5 02:40:31 2008
@@ -88,76 +88,58 @@ typedef struct {
uint64_t doctype_version;
} Ebml;
-typedef struct Track {
- MatroskaTrackType type;
+typedef struct {
+ uint64_t algo;
+ EbmlBin settings;
+} MatroskaTrackCompression;
- /* Unique track number and track ID. stream_index is the index that
- * the calling app uses for this track. */
- uint32_t num;
- uint32_t uid;
+typedef struct {
+ uint64_t scope;
+ uint64_t type;
+ MatroskaTrackCompression compression;
+} MatroskaTrackEncoding;
- char *name;
- char language[4];
+typedef struct {
+ double frame_rate;
+ uint64_t display_width;
+ uint64_t display_height;
+ uint64_t pixel_width;
+ uint64_t pixel_height;
+ uint64_t fourcc;
+} MatroskaTrackVideo;
- char *codec_id;
+typedef struct {
+ double samplerate;
+ double out_samplerate;
+ uint64_t bitdepth;
+ uint64_t channels;
- unsigned char *codec_priv;
- int codec_priv_size;
+ /* real audio header (extracted from extradata) */
+ int coded_framesize;
+ int sub_packet_h;
+ int frame_size;
+ int sub_packet_size;
+ int sub_packet_cnt;
+ int pkt_cnt;
+ uint8_t *buf;
+} MatroskaTrackAudio;
+typedef struct {
+ uint64_t num;
+ uint64_t type;
+ char *codec_id;
+ EbmlBin codec_priv;
+ char *language;
double time_scale;
uint64_t default_duration;
uint64_t flag_default;
-
- int encoding_scope;
- MatroskaTrackEncodingCompAlgo encoding_algo;
- uint8_t *encoding_settings;
- int encoding_settings_len;
+ MatroskaTrackVideo video;
+ MatroskaTrackAudio audio;
+ EbmlList encodings;
AVStream *stream;
} MatroskaTrack;
-typedef struct MatroskaVideoTrack {
- MatroskaTrack track;
-
- int pixel_width;
- int pixel_height;
- int display_width;
- int display_height;
-
- uint32_t fourcc;
-
- //..
-} MatroskaVideoTrack;
-
-typedef struct MatroskaAudioTrack {
- MatroskaTrack track;
-
- int channels;
- int bitdepth;
- int internal_samplerate;
- int samplerate;
- int block_align;
-
- /* real audio header */
- int coded_framesize;
- int sub_packet_h;
- int frame_size;
- int sub_packet_size;
- int sub_packet_cnt;
- int pkt_cnt;
- uint8_t *buf;
- //..
-} MatroskaAudioTrack;
-
-typedef struct MatroskaSubtitleTrack {
- MatroskaTrack track;
- //..
-} MatroskaSubtitleTrack;
-
-#define MAX_TRACK_SIZE (FFMAX3(sizeof(MatroskaVideoTrack), \
- sizeof(MatroskaAudioTrack), \
- sizeof(MatroskaSubtitleTrack)))
-
typedef struct {
char *filename;
char *mime;
@@ -198,15 +180,14 @@ typedef struct MatroskaDemuxContext {
uint64_t time_scale;
double duration;
char *title;
+ EbmlList tracks;
EbmlList attachments;
EbmlList chapters;
EbmlList index;
/* num_streams is the number of streams that av_new_stream() was called
* for ( = that are available to the calling program). */
- int num_tracks;
int num_streams;
- MatroskaTrack *tracks[MAX_STREAMS];
/* cache for ID peeking */
uint32_t peek_id;
@@ -259,6 +240,83 @@ static EbmlSyntax matroska_info[] = {
{ 0 }
};
+static EbmlSyntax matroska_track_video[] = {
+ { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT,0, offsetof(MatroskaTrackVideo,frame_rate) },
+ { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,display_width) },
+ { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,display_height) },
+ { 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_VIDEOFLAGINTERLACED,EBML_NONE },
+ { MATROSKA_ID_VIDEOSTEREOMODE, EBML_NONE },
+ { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE },
+ { EBML_ID_VOID, EBML_NONE },
+ { 0 }
+};
+
+static EbmlSyntax matroska_track_audio[] = {
+ { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT,0, offsetof(MatroskaTrackAudio,samplerate), {.f=8000.0} },
+ { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ,EBML_FLOAT,0,offsetof(MatroskaTrackAudio,out_samplerate) },
+ { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, offsetof(MatroskaTrackAudio,bitdepth) },
+ { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, offsetof(MatroskaTrackAudio,channels), {.u=1} },
+ { EBML_ID_VOID, EBML_NONE },
+ { 0 }
+};
+
+static EbmlSyntax matroska_track_encoding_compression[] = {
+ { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, offsetof(MatroskaTrackCompression,algo), {.u=0} },
+ { MATROSKA_ID_ENCODINGCOMPSETTINGS,EBML_BIN, 0, offsetof(MatroskaTrackCompression,settings) },
+ { EBML_ID_VOID, EBML_NONE },
+ { 0 }
+};
+
+static EbmlSyntax matroska_track_encoding[] = {
+ { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding,scope), {.u=1} },
+ { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding,type), {.u=0} },
+ { MATROSKA_ID_ENCODINGCOMPRESSION,EBML_NEST, 0, offsetof(MatroskaTrackEncoding,compression), {.n=matroska_track_encoding_compression} },
+ { EBML_ID_VOID, EBML_NONE },
+ { 0 }
+};
+
+static EbmlSyntax matroska_track_encodings[] = {
+ { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack,encodings), {.n=matroska_track_encoding} },
+ { EBML_ID_VOID, EBML_NONE },
+ { 0 }
+};
+
+static EbmlSyntax matroska_track[] = {
+ { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack,num) },
+ { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, offsetof(MatroskaTrack,type) },
+ { MATROSKA_ID_CODECID, EBML_STR, 0, offsetof(MatroskaTrack,codec_id) },
+ { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, offsetof(MatroskaTrack,codec_priv) },
+ { MATROSKA_ID_TRACKLANGUAGE, EBML_UTF8, 0, offsetof(MatroskaTrack,language), {.s="eng"} },
+ { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, offsetof(MatroskaTrack,default_duration) },
+ { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT,0, offsetof(MatroskaTrack,time_scale), {.f=1.0} },
+ { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTrack,flag_default), {.u=1} },
+ { 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_TRACKCONTENTENCODINGS,EBML_NEST, 0, 0, {.n=matroska_track_encodings} },
+ { MATROSKA_ID_TRACKUID, EBML_NONE },
+ { MATROSKA_ID_TRACKNAME, EBML_NONE },
+ { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE },
+ { MATROSKA_ID_TRACKFLAGFORCED, EBML_NONE },
+ { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE },
+ { MATROSKA_ID_CODECNAME, EBML_NONE },
+ { MATROSKA_ID_CODECDECODEALL, EBML_NONE },
+ { MATROSKA_ID_CODECINFOURL, EBML_NONE },
+ { MATROSKA_ID_CODECDOWNLOADURL, EBML_NONE },
+ { MATROSKA_ID_TRACKMINCACHE, EBML_NONE },
+ { MATROSKA_ID_TRACKMAXCACHE, EBML_NONE },
+ { EBML_ID_VOID, EBML_NONE },
+ { 0 }
+};
+
+static EbmlSyntax matroska_tracks[] = {
+ { MATROSKA_ID_TRACKENTRY, EBML_NEST, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext,tracks), {.n=matroska_track} },
+ { EBML_ID_VOID, EBML_NONE },
+ { 0 }
+};
+
static EbmlSyntax matroska_attachment[] = {
{ MATROSKA_ID_FILENAME, EBML_UTF8, 0, offsetof(MatroskaAttachement,filename) },
{ MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, offsetof(MatroskaAttachement,mime) },
@@ -826,11 +884,12 @@ static MatroskaTrack *
matroska_find_track_by_num (MatroskaDemuxContext *matroska,
int num)
{
+ MatroskaTrack *tracks = matroska->tracks.elem;
int i;
- for (i = 0; i < matroska->num_tracks; i++)
- if (matroska->tracks[i]->num == num)
- return matroska->tracks[i];
+ for (i=0; i < matroska->tracks.nb_elem; i++)
+ if (tracks[i].num == num)
+ return &tracks[i];
av_log(matroska->ctx, AV_LOG_ERROR, "Invalid track number %d\n", num);
return NULL;
@@ -1091,6 +1150,7 @@ matroska_parse_info (MatroskaDemuxContex
static int
matroska_decode_buffer(uint8_t** buf, int* buf_size, MatroskaTrack *track)
{
+ MatroskaTrackEncoding *encodings = track->encodings.elem;
uint8_t* data = *buf;
int isize = *buf_size;
uint8_t* pkt_data = NULL;
@@ -1098,9 +1158,9 @@ matroska_decode_buffer(uint8_t** buf, in
int result = 0;
int olen;
- switch (track->encoding_algo) {
+ switch (encodings[0].compression.algo) {
case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP:
- return track->encoding_settings_len;
+ return encodings[0].compression.settings.size;
case MATROSKA_TRACK_ENCODING_COMP_LZO:
do {
olen = pkt_size *= 3;
@@ -1165,611 +1225,76 @@ matroska_decode_buffer(uint8_t** buf, in
}
static int
-matroska_add_stream (MatroskaDemuxContext *matroska)
+matroska_parse_tracks (MatroskaDemuxContext *matroska)
{
- int res = 0;
- uint32_t id;
- MatroskaTrack *track;
-
- /* start with the master */
- if ((res = ebml_read_master(matroska, &id)) < 0)
- return res;
+ MatroskaTrack *tracks;
+ int i, res;
- av_log(matroska->ctx, AV_LOG_DEBUG, "parsing track, adding stream..,\n");
+ res = ebml_parse(matroska, matroska_tracks, matroska, MATROSKA_ID_TRACKS, 0);
- /* Allocate a generic track. */
- track = av_mallocz(MAX_TRACK_SIZE);
- track->time_scale = 1.0;
- strcpy(track->language, "eng");
+ tracks = matroska->tracks.elem;
+ for (i=0; i<matroska->tracks.nb_elem; i++) {
+ MatroskaTrack *track = &tracks[i];
+ EbmlList *encodings_list = &tracks->encodings;
+ MatroskaTrackEncoding *encodings = encodings_list->elem;
- /* try reading the trackentry headers */
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR(EIO);
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
+ if (track->type != MATROSKA_TRACK_TYPE_VIDEO &&
+ track->type != MATROSKA_TRACK_TYPE_AUDIO &&
+ track->type != MATROSKA_TRACK_TYPE_SUBTITLE) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown or unsupported track type %"PRIu64"\n",
+ track->type);
+ continue;
}
- switch (id) {
- /* track number (unique stream ID) */
- case MATROSKA_ID_TRACKNUMBER: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- track->num = num;
- break;
- }
-
- /* track UID (unique identifier) */
- case MATROSKA_ID_TRACKUID: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- track->uid = num;
- break;
- }
-
- /* track type (video, audio, combined, subtitle, etc.) */
- case MATROSKA_ID_TRACKTYPE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- if (track->type && track->type != num) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "More than one tracktype in an entry - skip\n");
- break;
- }
- track->type = num;
-
- switch (track->type) {
- case MATROSKA_TRACK_TYPE_VIDEO:
- case MATROSKA_TRACK_TYPE_AUDIO:
- case MATROSKA_TRACK_TYPE_SUBTITLE:
- break;
- case MATROSKA_TRACK_TYPE_COMPLEX:
- case MATROSKA_TRACK_TYPE_LOGO:
- case MATROSKA_TRACK_TYPE_CONTROL:
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown or unsupported track type 0x%x\n",
- track->type);
- track->type = MATROSKA_TRACK_TYPE_NONE;
- break;
- }
- break;
- }
-
- /* tracktype specific stuff for video */
- case MATROSKA_ID_TRACKVIDEO: {
- MatroskaVideoTrack *videotrack;
- if (!track->type)
- track->type = MATROSKA_TRACK_TYPE_VIDEO;
- if (track->type != MATROSKA_TRACK_TYPE_VIDEO) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "video data in non-video track - ignoring\n");
- res = AVERROR_INVALIDDATA;
- break;
- } else if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- videotrack = (MatroskaVideoTrack *)track;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR(EIO);
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* fixme, this should be one-up, but I get it here */
- case MATROSKA_ID_TRACKDEFAULTDURATION: {
- uint64_t num;
- if ((res = ebml_read_uint (matroska, &id,
- &num)) < 0)
- break;
- track->default_duration = num;
- break;
- }
-
- /* video framerate */
- case MATROSKA_ID_VIDEOFRAMERATE: {
- double num;
- if ((res = ebml_read_float(matroska, &id,
- &num)) < 0)
- break;
- if (!track->default_duration)
- track->default_duration = 1000000000/num;
- break;
- }
-
- /* width of the size to display the video at */
- case MATROSKA_ID_VIDEODISPLAYWIDTH: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->display_width = num;
- break;
- }
-
- /* height of the size to display the video at */
- case MATROSKA_ID_VIDEODISPLAYHEIGHT: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->display_height = num;
- break;
- }
-
- /* width of the video in the file */
- case MATROSKA_ID_VIDEOPIXELWIDTH: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->pixel_width = num;
- break;
- }
-
- /* height of the video in the file */
- case MATROSKA_ID_VIDEOPIXELHEIGHT: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->pixel_height = num;
- break;
- }
-
- /* whether the video is interlaced */
- case MATROSKA_ID_VIDEOFLAGINTERLACED: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- break;
- }
-
- /* colorspace (only matters for raw video)
- * fourcc */
- case MATROSKA_ID_VIDEOCOLORSPACE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->fourcc = num;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown video track header entry "
- "0x%x - ignoring\n", id);
- /* pass-through */
-
- case MATROSKA_ID_VIDEOSTEREOMODE:
- case MATROSKA_ID_VIDEOASPECTRATIO:
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
- break;
- }
-
- /* tracktype specific stuff for audio */
- case MATROSKA_ID_TRACKAUDIO: {
- MatroskaAudioTrack *audiotrack;
- if (!track->type)
- track->type = MATROSKA_TRACK_TYPE_AUDIO;
- if (track->type != MATROSKA_TRACK_TYPE_AUDIO) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "audio data in non-audio track - ignoring\n");
- res = AVERROR_INVALIDDATA;
- break;
- } else if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- audiotrack = (MatroskaAudioTrack *)track;
- audiotrack->channels = 1;
- audiotrack->samplerate = 8000;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR(EIO);
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* samplerate */
- case MATROSKA_ID_AUDIOSAMPLINGFREQ: {
- double num;
- if ((res = ebml_read_float(matroska, &id,
- &num)) < 0)
- break;
- audiotrack->internal_samplerate =
- audiotrack->samplerate = num;
- break;
- }
-
- case MATROSKA_ID_AUDIOOUTSAMPLINGFREQ: {
- double num;
- if ((res = ebml_read_float(matroska, &id,
- &num)) < 0)
- break;
- audiotrack->samplerate = num;
- break;
- }
-
- /* bitdepth */
- case MATROSKA_ID_AUDIOBITDEPTH: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- audiotrack->bitdepth = num;
- break;
- }
-
- /* channels */
- case MATROSKA_ID_AUDIOCHANNELS: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- audiotrack->channels = num;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown audio track header entry "
- "0x%x - ignoring\n", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
- break;
- }
-
- /* codec identifier */
- case MATROSKA_ID_CODECID: {
- char *text;
- if ((res = ebml_read_ascii(matroska, &id, &text)) < 0)
- break;
- track->codec_id = text;
- break;
- }
-
- /* codec private data */
- case MATROSKA_ID_CODECPRIVATE: {
- uint8_t *data;
- int size;
- if ((res = ebml_read_binary(matroska, &id, &data, &size) < 0))
- break;
- track->codec_priv = data;
- track->codec_priv_size = size;
- break;
- }
-
- /* name of this track */
- case MATROSKA_ID_TRACKNAME: {
- char *text;
- if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
- break;
- track->name = text;
- break;
- }
-
- /* language (matters for audio/subtitles, mostly) */
- case MATROSKA_ID_TRACKLANGUAGE: {
- char *text, *end;
- if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
- break;
- if ((end = strchr(text, '-')))
- *end = '\0';
- if (strlen(text) == 3)
- strcpy(track->language, text);
- av_free(text);
- break;
- }
-
- /* whether this is actually used */
- case MATROSKA_ID_TRACKFLAGENABLED: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- break;
- }
-
- /* whether it's the default for this track type */
- case MATROSKA_ID_TRACKFLAGDEFAULT: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- track->flag_default = num;
- break;
- }
-
- /* lacing (like MPEG, where blocks don't end/start on frame
- * boundaries) */
- case MATROSKA_ID_TRACKFLAGLACING: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- break;
- }
-
- /* default length (in time) of one data block in this track */
- case MATROSKA_ID_TRACKDEFAULTDURATION: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- track->default_duration = num;
- break;
- }
-
- case MATROSKA_ID_TRACKCONTENTENCODINGS: {
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR(EIO);
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- case MATROSKA_ID_TRACKCONTENTENCODING: {
- int encoding_scope = 1;
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR(EIO);
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- case MATROSKA_ID_ENCODINGSCOPE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- encoding_scope = num;
- break;
- }
-
- case MATROSKA_ID_ENCODINGTYPE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- if (num)
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Unsupported encoding type");
- break;
- }
-
- case MATROSKA_ID_ENCODINGCOMPRESSION: {
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR(EIO);
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- case MATROSKA_ID_ENCODINGCOMPALGO: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- if (num != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP &&
+ if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
+ if (!track->default_duration)
+ track->default_duration = 1000000000/track->video.frame_rate;
+ if (!track->video.display_width)
+ track->video.display_width = track->video.pixel_width;
+ if (!track->video.display_height)
+ track->video.display_height = track->video.pixel_height;
+ } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
+ if (!track->audio.out_samplerate)
+ track->audio.out_samplerate = track->audio.samplerate;
+ }
+ if (encodings_list->nb_elem > 1) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Multiple combined encodings no supported");
+ } else if (encodings_list->nb_elem == 1) {
+ if (encodings[0].type ||
+ (encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP &&
#ifdef CONFIG_ZLIB
- num != MATROSKA_TRACK_ENCODING_COMP_ZLIB &&
+ encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB &&
#endif
#ifdef CONFIG_BZLIB
- num != MATROSKA_TRACK_ENCODING_COMP_BZLIB &&
+ encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB &&
#endif
- num != MATROSKA_TRACK_ENCODING_COMP_LZO)
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Unsupported compression algo\n");
- track->encoding_algo = num;
- break;
- }
-
- case MATROSKA_ID_ENCODINGCOMPSETTINGS: {
- uint8_t *data;
- int size;
- if ((res = ebml_read_binary(matroska, &id, &data, &size) < 0))
- break;
- track->encoding_settings = data;
- track->encoding_settings_len = size;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown compression header entry "
- "0x%x - ignoring\n", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown content encoding header entry "
- "0x%x - ignoring\n", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- track->encoding_scope = encoding_scope;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown content encodings header entry "
- "0x%x - ignoring\n", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
+ encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO)) {
+ encodings[0].scope = 0;
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Unsupported encoding type");
+ } else if (track->codec_priv.size && encodings[0].scope&2) {
+ uint8_t *codec_priv = track->codec_priv.data;
+ int offset = matroska_decode_buffer(&track->codec_priv.data,
+ &track->codec_priv.size,
+ track);
+ if (offset < 0) {
+ track->codec_priv.data = NULL;
+ track->codec_priv.size = 0;
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Failed to decode codec private data\n");
+ } else if (offset > 0) {
+ track->codec_priv.data = av_malloc(track->codec_priv.size + offset);
+ memcpy(track->codec_priv.data,
+ encodings[0].compression.settings.data, offset);
+ memcpy(track->codec_priv.data+offset, codec_priv,
+ track->codec_priv.size);
+ track->codec_priv.size += offset;
}
- break;
- }
-
- case MATROSKA_ID_TRACKTIMECODESCALE: {
- double num;
- if ((res = ebml_read_float(matroska, &id, &num)) < 0)
- break;
- track->time_scale = num;
- break;
+ if (codec_priv != track->codec_priv.data)
+ av_free(codec_priv);
}
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown track header entry 0x%x - ignoring\n", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- /* we ignore these because they're nothing useful. */
- case MATROSKA_ID_TRACKFLAGFORCED:
- case MATROSKA_ID_CODECNAME:
- case MATROSKA_ID_CODECDECODEALL:
- case MATROSKA_ID_CODECINFOURL:
- case MATROSKA_ID_CODECDOWNLOADURL:
- case MATROSKA_ID_TRACKMINCACHE:
- case MATROSKA_ID_TRACKMAXCACHE:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- if (track->codec_priv_size && track->encoding_scope & 2) {
- uint8_t *orig_priv = track->codec_priv;
- int offset = matroska_decode_buffer(&track->codec_priv,
- &track->codec_priv_size, track);
- if (offset > 0) {
- track->codec_priv = av_malloc(track->codec_priv_size + offset);
- memcpy(track->codec_priv, track->encoding_settings, offset);
- memcpy(track->codec_priv+offset, orig_priv, track->codec_priv_size);
- track->codec_priv_size += offset;
- av_free(orig_priv);
- } else if (!offset) {
- av_free(orig_priv);
- } else
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Failed to decode codec private data\n");
- }
-
- if (track->type && matroska->num_tracks < ARRAY_SIZE(matroska->tracks)) {
- matroska->tracks[matroska->num_tracks++] = track;
- } else {
- av_free(track);
- }
- return res;
-}
-
-static int
-matroska_parse_tracks (MatroskaDemuxContext *matroska)
-{
- int res = 0;
- uint32_t id;
-
- av_log(matroska->ctx, AV_LOG_DEBUG, "parsing tracks...\n");
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR(EIO);
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* one track within the "all-tracks" header */
- case MATROSKA_ID_TRACKENTRY:
- res = matroska_add_stream(matroska);
- break;
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in track header\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
}
}
@@ -2121,8 +1646,6 @@ matroska_read_header (AVFormatContext
/* track info headers */
case MATROSKA_ID_TRACKS: {
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
res = matroska_parse_tracks(matroska);
break;
}
@@ -2188,16 +1711,16 @@ matroska_read_header (AVFormatContext
/* Have we found a cluster? */
if (ebml_peek_id(matroska, NULL) == MATROSKA_ID_CLUSTER) {
+ MatroskaTrack *tracks = matroska->tracks.elem;
int i, j;
- MatroskaTrack *track;
AVStream *st;
- for (i = 0; i < matroska->num_tracks; i++) {
+ for (i=0; i < matroska->tracks.nb_elem; i++) {
+ MatroskaTrack *track = &tracks[i];
enum CodecID codec_id = CODEC_ID_NONE;
uint8_t *extradata = NULL;
int extradata_size = 0;
int extradata_offset = 0;
- track = matroska->tracks[i];
/* Apply some sanity checks. */
if (track->codec_id == NULL)
@@ -2220,13 +1743,11 @@ matroska_read_header (AVFormatContext
* BITMAPINFOHEADER in the CodecPrivate. */
if (!strcmp(track->codec_id,
MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC) &&
- (track->codec_priv_size >= 40) &&
- (track->codec_priv != NULL)) {
- MatroskaVideoTrack *vtrack = (MatroskaVideoTrack *) track;
-
+ (track->codec_priv.size >= 40) &&
+ (track->codec_priv.data != NULL)) {
/* Offset of biCompression. Stored in LE. */
- vtrack->fourcc = AV_RL32(track->codec_priv + 16);
- codec_id = codec_get_id(codec_bmp_tags, vtrack->fourcc);
+ track->video.fourcc = AV_RL32(track->codec_priv.data + 16);
+ codec_id = codec_get_id(codec_bmp_tags, track->video.fourcc);
}
@@ -2234,36 +1755,31 @@ matroska_read_header (AVFormatContext
* WAVEFORMATEX in the CodecPrivate. */
else if (!strcmp(track->codec_id,
MATROSKA_CODEC_ID_AUDIO_ACM) &&
- (track->codec_priv_size >= 18) &&
- (track->codec_priv != NULL)) {
- uint16_t tag;
-
+ (track->codec_priv.size >= 18) &&
+ (track->codec_priv.data != NULL)) {
/* Offset of wFormatTag. Stored in LE. */
- tag = AV_RL16(track->codec_priv);
+ uint16_t tag = AV_RL16(track->codec_priv.data);
codec_id = codec_get_id(codec_wav_tags, tag);
}
if (!strcmp(track->codec_id, "V_QUICKTIME") &&
- (track->codec_priv_size >= 86) &&
- (track->codec_priv != NULL)) {
- MatroskaVideoTrack *vtrack = (MatroskaVideoTrack *) track;
-
- vtrack->fourcc = AV_RL32(track->codec_priv);
- codec_id = codec_get_id(codec_movvideo_tags, vtrack->fourcc);
+ (track->codec_priv.size >= 86) &&
+ (track->codec_priv.data != NULL)) {
+ track->video.fourcc = AV_RL32(track->codec_priv.data);
+ codec_id=codec_get_id(codec_movvideo_tags, track->video.fourcc);
}
- else if (codec_id == CODEC_ID_AAC && !track->codec_priv_size) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
+ else if (codec_id == CODEC_ID_AAC && !track->codec_priv.size) {
int profile = matroska_aac_profile(track->codec_id);
- int sri = matroska_aac_sri(audiotrack->internal_samplerate);
+ int sri = matroska_aac_sri(track->audio.samplerate);
extradata = av_malloc(5);
if (extradata == NULL)
return AVERROR(ENOMEM);
extradata[0] = (profile << 3) | ((sri&0x0E) >> 1);
- extradata[1] = ((sri&0x01) << 7) | (audiotrack->channels<<3);
+ extradata[1] = ((sri&0x01) << 7) | (track->audio.channels<<3);
if (strstr(track->codec_id, "SBR")) {
- sri = matroska_aac_sri(audiotrack->samplerate);
+ sri = matroska_aac_sri(track->audio.out_samplerate);
extradata[2] = 0x56;
extradata[3] = 0xE5;
extradata[4] = 0x80 | (sri<<3);
@@ -2274,7 +1790,6 @@ matroska_read_header (AVFormatContext
}
else if (codec_id == CODEC_ID_TTA) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
ByteIOContext b;
extradata_size = 30;
extradata = av_mallocz(extradata_size);
@@ -2284,46 +1799,44 @@ matroska_read_header (AVFormatContext
NULL, NULL, NULL, NULL);
put_buffer(&b, "TTA1", 4);
put_le16(&b, 1);
- put_le16(&b, audiotrack->channels);
- put_le16(&b, audiotrack->bitdepth);
- put_le32(&b, audiotrack->samplerate);
- put_le32(&b, matroska->ctx->duration * audiotrack->samplerate);
+ put_le16(&b, track->audio.channels);
+ put_le16(&b, track->audio.bitdepth);
+ put_le32(&b, track->audio.out_samplerate);
+ put_le32(&b, matroska->ctx->duration * track->audio.out_samplerate);
}
else if (codec_id == CODEC_ID_RV10 || codec_id == CODEC_ID_RV20 ||
codec_id == CODEC_ID_RV30 || codec_id == CODEC_ID_RV40) {
extradata_offset = 26;
- track->codec_priv_size -= extradata_offset;
+ track->codec_priv.size -= extradata_offset;
}
else if (codec_id == CODEC_ID_RA_144) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
- audiotrack->samplerate = 8000;
- audiotrack->channels = 1;
+ track->audio.out_samplerate = 8000;
+ track->audio.channels = 1;
}
else if (codec_id == CODEC_ID_RA_288 ||
codec_id == CODEC_ID_COOK ||
codec_id == CODEC_ID_ATRAC3) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
ByteIOContext b;
- init_put_byte(&b, track->codec_priv, track->codec_priv_size, 0,
- NULL, NULL, NULL, NULL);
+ init_put_byte(&b, track->codec_priv.data,track->codec_priv.size,
+ 0, NULL, NULL, NULL, NULL);
url_fskip(&b, 24);
- audiotrack->coded_framesize = get_be32(&b);
+ track->audio.coded_framesize = get_be32(&b);
url_fskip(&b, 12);
- audiotrack->sub_packet_h = get_be16(&b);
- audiotrack->frame_size = get_be16(&b);
- audiotrack->sub_packet_size = get_be16(&b);
- audiotrack->buf = av_malloc(audiotrack->frame_size * audiotrack->sub_packet_h);
+ track->audio.sub_packet_h = get_be16(&b);
+ track->audio.frame_size = get_be16(&b);
+ track->audio.sub_packet_size = get_be16(&b);
+ track->audio.buf = av_malloc(track->audio.frame_size * track->audio.sub_packet_h);
if (codec_id == CODEC_ID_RA_288) {
- audiotrack->block_align = audiotrack->coded_framesize;
- track->codec_priv_size = 0;
+ st->codec->block_align = track->audio.coded_framesize;
+ track->codec_priv.size = 0;
} else {
- audiotrack->block_align = audiotrack->sub_packet_size;
+ st->codec->block_align = track->audio.sub_packet_size;
extradata_offset = 78;
- track->codec_priv_size -= extradata_offset;
+ track->codec_priv.size -= extradata_offset;
}
}
@@ -2350,39 +1863,31 @@ matroska_read_header (AVFormatContext
if(extradata){
st->codec->extradata = extradata;
st->codec->extradata_size = extradata_size;
- } else if(track->codec_priv && track->codec_priv_size > 0){
- st->codec->extradata = av_malloc(track->codec_priv_size);
+ } else if(track->codec_priv.data && track->codec_priv.size > 0){
+ st->codec->extradata = av_malloc(track->codec_priv.size);
if(st->codec->extradata == NULL)
return AVERROR(ENOMEM);
- st->codec->extradata_size = track->codec_priv_size;
- memcpy(st->codec->extradata,track->codec_priv+extradata_offset,
- track->codec_priv_size);
+ st->codec->extradata_size = track->codec_priv.size;
+ memcpy(st->codec->extradata,
+ track->codec_priv.data + extradata_offset,
+ track->codec_priv.size);
}
if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
- MatroskaVideoTrack *videotrack = (MatroskaVideoTrack *)track;
-
st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_tag = videotrack->fourcc;
- st->codec->width = videotrack->pixel_width;
- st->codec->height = videotrack->pixel_height;
- if (videotrack->display_width == 0)
- videotrack->display_width= videotrack->pixel_width;
- if (videotrack->display_height == 0)
- videotrack->display_height= videotrack->pixel_height;
+ st->codec->codec_tag = track->video.fourcc;
+ st->codec->width = track->video.pixel_width;
+ st->codec->height = track->video.pixel_height;
av_reduce(&st->codec->sample_aspect_ratio.num,
&st->codec->sample_aspect_ratio.den,
- st->codec->height * videotrack->display_width,
- st->codec-> width * videotrack->display_height,
+ st->codec->height * track->video.display_width,
+ st->codec-> width * track->video.display_height,
255);
st->need_parsing = AVSTREAM_PARSE_HEADERS;
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
-
st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->sample_rate = audiotrack->samplerate;
- st->codec->channels = audiotrack->channels;
- st->codec->block_align = audiotrack->block_align;
+ st->codec->sample_rate = track->audio.out_samplerate;
+ st->codec->channels = track->audio.channels;
} else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) {
st->codec->codec_type = CODEC_TYPE_SUBTITLE;
}
@@ -2554,43 +2059,43 @@ matroska_parse_block(MatroskaDemuxContex
if (st->codec->codec_id == CODEC_ID_RA_288 ||
st->codec->codec_id == CODEC_ID_COOK ||
st->codec->codec_id == CODEC_ID_ATRAC3) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
int a = st->codec->block_align;
- int sps = audiotrack->sub_packet_size;
- int cfs = audiotrack->coded_framesize;
- int h = audiotrack->sub_packet_h;
- int y = audiotrack->sub_packet_cnt;
- int w = audiotrack->frame_size;
+ int sps = track->audio.sub_packet_size;
+ int cfs = track->audio.coded_framesize;
+ int h = track->audio.sub_packet_h;
+ int y = track->audio.sub_packet_cnt;
+ int w = track->audio.frame_size;
int x;
- if (!audiotrack->pkt_cnt) {
+ if (!track->audio.pkt_cnt) {
if (st->codec->codec_id == CODEC_ID_RA_288)
for (x=0; x<h/2; x++)
- memcpy(audiotrack->buf+x*2*w+y*cfs,
+ memcpy(track->audio.buf+x*2*w+y*cfs,
data+x*cfs, cfs);
else
for (x=0; x<w/sps; x++)
- memcpy(audiotrack->buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
+ memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
- if (++audiotrack->sub_packet_cnt >= h) {
- audiotrack->sub_packet_cnt = 0;
- audiotrack->pkt_cnt = h*w / a;
+ if (++track->audio.sub_packet_cnt >= h) {
+ track->audio.sub_packet_cnt = 0;
+ track->audio.pkt_cnt = h*w / a;
}
}
- while (audiotrack->pkt_cnt) {
+ while (track->audio.pkt_cnt) {
pkt = av_mallocz(sizeof(AVPacket));
av_new_packet(pkt, a);
- memcpy(pkt->data, audiotrack->buf
- + a * (h*w / a - audiotrack->pkt_cnt--), a);
+ memcpy(pkt->data, track->audio.buf
+ + a * (h*w / a - track->audio.pkt_cnt--), a);
pkt->pos = pos;
pkt->stream_index = st->index;
matroska_queue_packet(matroska, pkt);
}
} else {
+ MatroskaTrackEncoding *encodings = track->encodings.elem;
int offset = 0, pkt_size = lace_size[n];
uint8_t *pkt_data = data;
- if (track->encoding_scope & 1) {
+ if (encodings && encodings->scope & 1) {
offset = matroska_decode_buffer(&pkt_data, &pkt_size,
track);
if (offset < 0)
@@ -2606,7 +2111,7 @@ matroska_parse_block(MatroskaDemuxContex
break;
}
if (offset)
- memcpy (pkt->data, track->encoding_settings, offset);
+ memcpy (pkt->data, encodings->compression.settings.data, offset);
memcpy (pkt->data+offset, pkt_data, pkt_size);
if (pkt_data != data)
@@ -2857,23 +2362,15 @@ static int
matroska_read_close (AVFormatContext *s)
{
MatroskaDemuxContext *matroska = s->priv_data;
+ MatroskaTrack *tracks = matroska->tracks.elem;
int n = 0;
matroska_clear_queue(matroska);
- for (n = 0; n < matroska->num_tracks; n++) {
- MatroskaTrack *track = matroska->tracks[n];
- av_free(track->codec_id);
- av_free(track->codec_priv);
- av_free(track->name);
-
- if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
- av_free(audiotrack->buf);
- }
-
- av_free(track);
- }
+ for (n=0; n < matroska->tracks.nb_elem; n++)
+ if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO)
+ av_free(tracks[n].audio.buf);
+ ebml_free(matroska_tracks, matroska);
ebml_free(matroska_index, matroska);
return 0;
More information about the ffmpeg-cvslog
mailing list