X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmatroska.c;h=3d6d9756900063af4fd66e0ddeefce71146f5b84;hb=4d41f3eea069a418139b2d2ef74dfc48a3e01aaf;hp=f5429298c6b7498dba24292d58709439a59d159d;hpb=d5be317cbe20c1e1ace27d84a4f3cad2a694bffc;p=ffmpeg diff --git a/libavformat/matroska.c b/libavformat/matroska.c index f5429298c6b..3d6d9756900 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -2,19 +2,21 @@ * Matroska file demuxer (no muxer yet) * Copyright (c) 2003-2004 The ffmpeg Project * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -27,8 +29,9 @@ */ #include "avformat.h" -/* For codec_get_bmp_id and codec_get_wav_id. */ -#include "avi.h" +/* For codec_get_id(). */ +#include "riff.h" +#include "intfloat_readwrite.h" /* EBML version supported */ #define EBML_VERSION 1 @@ -66,6 +69,7 @@ /* IDs in the info master */ #define MATROSKA_ID_TIMECODESCALE 0x2AD7B1 #define MATROSKA_ID_DURATION 0x4489 +#define MATROSKA_ID_TITLE 0x7BA9 #define MATROSKA_ID_WRITINGAPP 0x5741 #define MATROSKA_ID_MUXINGAPP 0x4D80 #define MATROSKA_ID_DATEUTC 0x4461 @@ -106,6 +110,8 @@ /* IDs in the trackaudio master */ #define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5 +#define MATROSKA_ID_AUDIOOUTSAMPLINGFREQ 0x78B5 + #define MATROSKA_ID_AUDIOBITDEPTH 0x6264 #define MATROSKA_ID_AUDIOCHANNELS 0x9F @@ -133,6 +139,7 @@ /* IDs in the cluster master */ #define MATROSKA_ID_CLUSTERTIMECODE 0xE7 #define MATROSKA_ID_BLOCKGROUP 0xA0 +#define MATROSKA_ID_SIMPLEBLOCK 0xA3 /* IDs in the blockgroup master */ #define MATROSKA_ID_BLOCK 0xA1 @@ -170,6 +177,7 @@ typedef enum { MATROSKA_TRACK_ENABLED = (1<<0), MATROSKA_TRACK_DEFAULT = (1<<1), MATROSKA_TRACK_LACING = (1<<2), + MATROSKA_TRACK_REAL_V = (1<<4), MATROSKA_TRACK_SHIFT = (1<<16) } MatroskaTrackFlags; @@ -181,32 +189,48 @@ typedef enum { * Matroska Codec IDs. Strings. */ +typedef struct CodecTags{ + const char *str; + enum CodecID id; +}CodecTags; + #define MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC "V_MS/VFW/FOURCC" -#define MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED "V_UNCOMPRESSED" -#define MATROSKA_CODEC_ID_VIDEO_MPEG4_SP "V_MPEG4/ISO/SP" -#define MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP "V_MPEG4/ISO/ASP" -#define MATROSKA_CODEC_ID_VIDEO_MPEG4_AP "V_MPEG4/ISO/AP" -#define MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC "V_MPEG4/ISO/AVC" -#define MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3 "V_MPEG4/MS/V3" -#define MATROSKA_CODEC_ID_VIDEO_MPEG1 "V_MPEG1" -#define MATROSKA_CODEC_ID_VIDEO_MPEG2 "V_MPEG2" -#define MATROSKA_CODEC_ID_VIDEO_MJPEG "V_MJPEG" +#define MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM" + +static CodecTags codec_tags[]={ +// {"V_MS/VFW/FOURCC" , CODEC_ID_NONE}, + {"V_UNCOMPRESSED" , CODEC_ID_RAWVIDEO}, + {"V_MPEG4/ISO/SP" , CODEC_ID_MPEG4}, + {"V_MPEG4/ISO/ASP" , CODEC_ID_MPEG4}, + {"V_MPEG4/ISO/AP" , CODEC_ID_MPEG4}, + {"V_MPEG4/ISO/AVC" , CODEC_ID_H264}, + {"V_MPEG4/MS/V3" , CODEC_ID_MSMPEG4V3}, + {"V_MPEG1" , CODEC_ID_MPEG1VIDEO}, + {"V_MPEG2" , CODEC_ID_MPEG2VIDEO}, + {"V_MJPEG" , CODEC_ID_MJPEG}, + {"V_REAL/RV10" , CODEC_ID_RV10}, + {"V_REAL/RV20" , CODEC_ID_RV20}, + {"V_REAL/RV30" , CODEC_ID_RV30}, + {"V_REAL/RV40" , CODEC_ID_RV40}, /* TODO: Real/Quicktime */ -#define MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM" -#define MATROSKA_CODEC_ID_AUDIO_MPEG1_L1 "A_MPEG/L1" -#define MATROSKA_CODEC_ID_AUDIO_MPEG1_L2 "A_MPEG/L2" -#define MATROSKA_CODEC_ID_AUDIO_MPEG1_L3 "A_MPEG/L3" -#define MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE "A_PCM/INT/BIG" -#define MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE "A_PCM/INT/LIT" -#define MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT "A_PCM/FLOAT/IEEE" -#define MATROSKA_CODEC_ID_AUDIO_AC3 "A_AC3" -#define MATROSKA_CODEC_ID_AUDIO_DTS "A_DTS" -#define MATROSKA_CODEC_ID_AUDIO_VORBIS "A_VORBIS" -#define MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM" -#define MATROSKA_CODEC_ID_AUDIO_MPEG2 "A_AAC/MPEG2/" -#define MATROSKA_CODEC_ID_AUDIO_MPEG4 "A_AAC/MPEG4/" +// {"A_MS/ACM" , CODEC_ID_NONE}, + {"A_MPEG/L1" , CODEC_ID_MP3}, + {"A_MPEG/L2" , CODEC_ID_MP3}, + {"A_MPEG/L3" , CODEC_ID_MP3}, + {"A_PCM/INT/BIG" , CODEC_ID_PCM_U16BE}, + {"A_PCM/INT/LIT" , CODEC_ID_PCM_U16LE}, +// {"A_PCM/FLOAT/IEEE" , CODEC_ID_NONE}, + {"A_AC3" , CODEC_ID_AC3}, + {"A_DTS" , CODEC_ID_DTS}, + {"A_VORBIS" , CODEC_ID_VORBIS}, + {"A_AAC" , CODEC_ID_AAC}, + {"A_FLAC" , CODEC_ID_FLAC}, + {"A_WAVPACK4" , CODEC_ID_WAVPACK}, + {"A_TTA1" , CODEC_ID_TTA}, + {NULL , CODEC_ID_NONE} /* TODO: AC3-9/10 (?), Real, Musepack, Quicktime */ +}; /* max. depth in the EBML tree structure */ #define EBML_MAX_DEPTH 16 @@ -254,6 +278,7 @@ typedef struct MatroskaAudioTrack { int channels, bitdepth, + internal_samplerate, samplerate; //.. } MatroskaAudioTrack; @@ -264,6 +289,10 @@ typedef struct MatroskaSubtitleTrack { //.. } MatroskaSubtitleTrack; +#define MAX_TRACK_SIZE (FFMAX(FFMAX(sizeof(MatroskaVideoTrack), \ + sizeof(MatroskaAudioTrack)), \ + sizeof(MatroskaSubtitleTrack))) + typedef struct MatroskaLevel { uint64_t start, length; } MatroskaLevel; @@ -290,9 +319,8 @@ typedef struct MatroskaDemuxContext { /* timescale in the file */ int64_t time_scale; - /* length, position (time, ns) */ - int64_t duration, - pos; + /* position (time, ns) */ + int64_t pos; /* num_streams is the number of streams that av_new_stream() was called * for ( = that are available to the calling program). */ @@ -379,7 +407,7 @@ ebml_read_num (MatroskaDemuxContext *matroska, if (!url_feof(pb)) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, - "Read error at pos. %llu (0x%llx)\n", + "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos); } return AVERROR_IO; /* EOS or actual I/O error */ @@ -393,7 +421,7 @@ ebml_read_num (MatroskaDemuxContext *matroska, if (read > max_size) { offset_t pos = url_ftell(pb) - 1; av_log(matroska->ctx, AV_LOG_ERROR, - "Invalid EBML number size tag 0x%02x at pos %llu (0x%llx)\n", + "Invalid EBML number size tag 0x%02x at pos %"PRIu64" (0x%"PRIx64")\n", (uint8_t) total, pos, pos); return AVERROR_INVALIDDATA; } @@ -537,7 +565,7 @@ ebml_read_uint (MatroskaDemuxContext *matroska, if (size < 1 || size > 8) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, - "Invalid uint element size %d at position %lld (0x%llx)\n", + "Invalid uint element size %d at position %"PRId64" (0x%"PRIx64")\n", size, pos, pos); return AVERROR_INVALIDDATA; } @@ -571,7 +599,7 @@ ebml_read_sint (MatroskaDemuxContext *matroska, if (size < 1 || size > 8) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, - "Invalid sint element size %d at position %lld (0x%llx)\n", + "Invalid sint element size %d at position %"PRId64" (0x%"PRIx64")\n", size, pos, pos); return AVERROR_INVALIDDATA; } @@ -579,7 +607,6 @@ ebml_read_sint (MatroskaDemuxContext *matroska, negative = 1; *num &= ~0x80; } - *num = 0; while (n++ < size) *num = (*num << 8) | get_byte(pb); @@ -597,8 +624,8 @@ ebml_read_sint (MatroskaDemuxContext *matroska, static int ebml_read_float (MatroskaDemuxContext *matroska, - uint32_t *id, - double *num) + uint32_t *id, + double *num) { ByteIOContext *pb = &matroska->ctx->pb; int size, res; @@ -609,42 +636,17 @@ ebml_read_float (MatroskaDemuxContext *matroska, return res; size = rlength; - if (size != 4 && size != 8 && size != 10) { + if (size == 4) { + *num= av_int2flt(get_be32(pb)); + } else if(size==8){ + *num= av_int2dbl(get_be64(pb)); + } else{ offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, - "Invalid float element size %d at position %llu (0x%llx)\n", + "Invalid float element size %d at position %"PRIu64" (0x%"PRIx64")\n", size, pos, pos); return AVERROR_INVALIDDATA; } - if (size == 10) { - av_log(matroska->ctx, AV_LOG_ERROR, - "FIXME! 10-byte floats unimplemented\n"); - return AVERROR_UNKNOWN; - } - - if (size == 4) { - float f; - - while (size-- > 0) -#ifdef WORDS_BIGENDIAN - ((uint8_t *) &f)[3 - size] = get_byte(pb); -#else - ((uint8_t *) &f)[size] = get_byte(pb); -#endif - - *num = f; - } else { - double d; - - while (size-- > 0) -#ifdef WORDS_BIGENDIAN - ((uint8_t *) &d)[7 - size] = get_byte(pb); -#else - ((uint8_t *) &d)[size] = get_byte(pb); -#endif - - *num = d; - } return 0; } @@ -677,7 +679,7 @@ ebml_read_ascii (MatroskaDemuxContext *matroska, if (get_buffer(pb, (uint8_t *) *str, size) != size) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, - "Read error at pos. %llu (0x%llx)\n", pos, pos); + "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos); return AVERROR_IO; } (*str)[size] = '\0'; @@ -774,7 +776,7 @@ ebml_read_binary (MatroskaDemuxContext *matroska, if (get_buffer(pb, *binary, *size) != *size) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, - "Read error at pos. %llu (0x%llx)\n", pos, pos); + "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos); return AVERROR_IO; } @@ -817,9 +819,6 @@ matroska_ebmlnum_uint (uint8_t *data, n++; } - if (!total) - return AVERROR_INVALIDDATA; - if (read == num_ffs) *num = (uint64_t)-1; else @@ -898,7 +897,7 @@ ebml_read_header (MatroskaDemuxContext *matroska, return res; if (num > EBML_VERSION) { av_log(matroska->ctx, AV_LOG_ERROR, - "EBML version %llu (> %d) is not supported\n", + "EBML version %"PRIu64" (> %d) is not supported\n", num, EBML_VERSION); return AVERROR_INVALIDDATA; } @@ -913,7 +912,7 @@ ebml_read_header (MatroskaDemuxContext *matroska, return res; if (num > sizeof(uint64_t)) { av_log(matroska->ctx, AV_LOG_ERROR, - "Integers of size %llu (> %d) not supported\n", + "Integers of size %"PRIu64" (> %zd) not supported\n", num, sizeof(uint64_t)); return AVERROR_INVALIDDATA; } @@ -928,8 +927,8 @@ ebml_read_header (MatroskaDemuxContext *matroska, return res; if (num > sizeof(uint32_t)) { av_log(matroska->ctx, AV_LOG_ERROR, - "IDs of size %llu (> %u) not supported\n", - num, sizeof(uint32_t)); + "IDs of size %"PRIu64" (> %zu) not supported\n", + num, sizeof(uint32_t)); return AVERROR_INVALIDDATA; } break; @@ -996,8 +995,7 @@ matroska_deliver_packet (MatroskaDemuxContext *matroska, av_realloc(matroska->packets, (matroska->num_packets - 1) * sizeof(AVPacket *)); } else { - av_free(matroska->packets); - matroska->packets = NULL; + av_freep(&matroska->packets); } matroska->num_packets--; return 0; @@ -1061,7 +1059,7 @@ matroska_probe (AVProbeData *p) * we don't parse the whole header but simply check for the * availability of that array of characters inside the header. * Not fully fool-proof, but good enough. */ - for (n = 4 + size; n < 4 + size + total - sizeof(probe_data); n++) + for (n = 4 + size; n <= 4 + size + total - sizeof(probe_data); n++) if (!memcmp (&p->buf[n], probe_data, sizeof(probe_data))) return AVPROBE_SCORE_MAX; @@ -1103,7 +1101,17 @@ matroska_parse_info (MatroskaDemuxContext *matroska) double num; if ((res = ebml_read_float(matroska, &id, &num)) < 0) break; - matroska->duration = num * matroska->time_scale; + matroska->ctx->duration = num * matroska->time_scale * 1000 / AV_TIME_BASE; + break; + } + + case MATROSKA_ID_TITLE: { + char *text; + if ((res = ebml_read_utf8(matroska, &id, &text)) < 0) + break; + strncpy(matroska->ctx->title, text, + sizeof(matroska->ctx->title)-1); + av_free(text); break; } @@ -1160,7 +1168,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska) av_log(matroska->ctx, AV_LOG_DEBUG, "parsing track, adding stream..,\n"); /* Allocate a generic track. As soon as we know its type we'll realloc. */ - track = av_mallocz(sizeof(MatroskaTrack)); + track = av_mallocz(MAX_TRACK_SIZE); matroska->num_tracks++; /* start with the master */ @@ -1199,30 +1207,19 @@ matroska_add_stream (MatroskaDemuxContext *matroska) /* track type (video, audio, combined, subtitle, etc.) */ case MATROSKA_ID_TRACKTYPE: { uint64_t num; - if (track->type != 0) { + 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; } - if ((res = ebml_read_uint(matroska, &id, &num)) < 0) - break; track->type = num; - /* ok, so we're actually going to reallocate this thing */ switch (track->type) { case MATROSKA_TRACK_TYPE_VIDEO: - track = (MatroskaTrack *) - av_realloc(track, sizeof(MatroskaVideoTrack)); - break; case MATROSKA_TRACK_TYPE_AUDIO: - track = (MatroskaTrack *) - av_realloc(track, sizeof(MatroskaAudioTrack)); - ((MatroskaAudioTrack *)track)->channels = 1; - ((MatroskaAudioTrack *)track)->samplerate = 8000; - break; case MATROSKA_TRACK_TYPE_SUBTITLE: - track = (MatroskaTrack *) - av_realloc(track, sizeof(MatroskaSubtitleTrack)); break; case MATROSKA_TRACK_TYPE_COMPLEX: case MATROSKA_TRACK_TYPE_LOGO: @@ -1241,6 +1238,8 @@ matroska_add_stream (MatroskaDemuxContext *matroska) /* 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"); @@ -1408,6 +1407,8 @@ matroska_add_stream (MatroskaDemuxContext *matroska) /* 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"); @@ -1416,6 +1417,8 @@ matroska_add_stream (MatroskaDemuxContext *matroska) } 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))) { @@ -1429,6 +1432,16 @@ matroska_add_stream (MatroskaDemuxContext *matroska) 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) @@ -1677,7 +1690,7 @@ matroska_parse_index (MatroskaDemuxContext *matroska) switch (id) { /* one single index entry ('point') */ case MATROSKA_ID_CUETIME: { - int64_t time; + uint64_t time; if ((res = ebml_read_uint(matroska, &id, &time)) < 0) break; @@ -1685,7 +1698,7 @@ matroska_parse_index (MatroskaDemuxContext *matroska) break; } - /* position in the file + track to which it + /* position in the file + track to which it * belongs */ case MATROSKA_ID_CUETRACKPOSITION: if ((res = ebml_read_master(matroska, &id)) < 0) @@ -1891,7 +1904,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) if (!seek_id || seek_pos == (uint64_t) -1) { av_log(matroska->ctx, AV_LOG_INFO, - "Incomplete seekhead entry (0x%x/%llu)\n", + "Incomplete seekhead entry (0x%x/%"PRIu64")\n", seek_id, seek_pos); break; } @@ -1921,7 +1934,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) "cannot parse further.\n", EBML_MAX_DEPTH); return AVERROR_UNKNOWN; } - + level.start = 0; level.length = (uint64_t)-1; matroska->levels[matroska->num_levels] = level; @@ -1930,11 +1943,11 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) /* check ID */ if (!(id = ebml_peek_id (matroska, &matroska->level_up))) - break; + goto finish; if (id != seek_id) { av_log(matroska->ctx, AV_LOG_INFO, "We looked for ID=0x%x but got " - "ID=0x%x (pos=%llu)", + "ID=0x%x (pos=%"PRIu64")", seek_id, id, seek_pos + matroska->segment_start); goto finish; @@ -1942,7 +1955,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) /* read master + parse */ if ((res = ebml_read_master(matroska, &id)) < 0) - break; + goto finish; switch (id) { case MATROSKA_ID_CUES: if (!(res = matroska_parse_index(matroska)) || @@ -1959,8 +1972,6 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) } break; } - if (res < 0) - break; finish: /* remove dummy level */ @@ -2009,6 +2020,37 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) return res; } +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x)) + +static int +matroska_aac_profile (char *codec_id) +{ + static const char *aac_profiles[] = { + "MAIN", "LC", "SSR" + }; + int profile; + + for (profile=0; profile 2) { av_log(matroska->ctx, AV_LOG_ERROR, - "Matroska demuxer version 1 too old for file version %d\n", + "Matroska demuxer version 2 too old for file version %d\n", version); return AVERROR_NOFMT; } @@ -2143,19 +2185,17 @@ matroska_read_header (AVFormatContext *s, } } - if (res < 0) - return res; - /* Have we found a cluster? */ - if (res == 1) { - int i; - enum CodecID codec_id; + if (ebml_peek_id(matroska, NULL) == MATROSKA_ID_CLUSTER) { + int i, j; MatroskaTrack *track; AVStream *st; - void *extradata = NULL; - int extradata_size = 0; for (i = 0; i < matroska->num_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]; /* libavformat does not really support subtitles. @@ -2164,6 +2204,14 @@ matroska_read_header (AVFormatContext *s, (track->codec_id == NULL)) continue; + for(j=0; codec_tags[j].str; j++){ + if(!strncmp(codec_tags[j].str, track->codec_id, + strlen(codec_tags[j].str))){ + codec_id= codec_tags[j].id; + break; + } + } + /* Set the FourCC from the CodecID. */ /* This is the MS compatibility mode which stores a * BITMAPINFOHEADER in the CodecPrivate. */ @@ -2177,33 +2225,13 @@ matroska_read_header (AVFormatContext *s, p = (unsigned char *)track->codec_priv + 16; ((MatroskaVideoTrack *)track)->fourcc = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; - codec_id = codec_get_bmp_id(((MatroskaVideoTrack *)track)->fourcc); - - } else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_VIDEO_MPEG4_SP) || - !strcmp(track->codec_id, - MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP) || - !strcmp(track->codec_id, - MATROSKA_CODEC_ID_VIDEO_MPEG4_AP)) - codec_id = CODEC_ID_MPEG4; - else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC)) - codec_id = CODEC_ID_H264; -/* else if (!strcmp(track->codec_id, */ -/* MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) */ -/* codec_id = CODEC_ID_???; */ - else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3)) - codec_id = CODEC_ID_MSMPEG4V3; - else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_VIDEO_MPEG1) || - !strcmp(track->codec_id, - MATROSKA_CODEC_ID_VIDEO_MPEG2)) - codec_id = CODEC_ID_MPEG2VIDEO; + codec_id = codec_get_id(codec_bmp_tags, ((MatroskaVideoTrack *)track)->fourcc); + + } /* This is the MS compatibility mode which stores a * WAVEFORMATEX in the CodecPrivate. */ - else if (!strcmp(track->codec_id, + else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_AUDIO_ACM) && (track->codec_priv_size >= 18) && (track->codec_priv != NULL)) { @@ -2213,82 +2241,53 @@ matroska_read_header (AVFormatContext *s, /* Offset of wFormatTag. Stored in LE. */ p = (unsigned char *)track->codec_priv; tag = (p[1] << 8) | p[0]; - codec_id = codec_get_wav_id(tag); - - } else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) || - !strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) || - !strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) - codec_id = CODEC_ID_MP3; - else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE)) - codec_id = CODEC_ID_PCM_U16BE; - else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE)) - codec_id = CODEC_ID_PCM_U16LE; -/* else if (!strcmp(track->codec_id, */ -/* MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) */ -/* codec_id = CODEC_ID_PCM_???; */ - else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_AC3)) - codec_id = CODEC_ID_AC3; - else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_DTS)) - codec_id = CODEC_ID_DTS; - /* No such codec id so far. */ -/* else if (!strcmp(track->codec_id, */ -/* MATROSKA_CODEC_ID_AUDIO_DTS)) */ -/* codec_id = CODEC_ID_DTS; */ - else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_VORBIS)) { - u_char *p = track->codec_priv, *cdp; - int cps = track->codec_priv_size; - int nf, s[3], cds; - int i; - - nf = *p++; - cps--; - - if(nf != 2) - continue; - - for(i = 0; i < 2; i++){ - int xv; - s[i] = 0; - do { - xv = *p++; - s[i] += xv; - cps--; - } while(xv == 255); - } + codec_id = codec_get_id(codec_wav_tags, tag); - s[2] = cps - s[0] - s[1]; + } - cds = cps + 6; - extradata = cdp = av_malloc(cds); - if(extradata == NULL) + else if (codec_id == CODEC_ID_AAC && !track->codec_priv_size) { + MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track; + int profile = matroska_aac_profile(track->codec_id); + int sri = matroska_aac_sri(audiotrack->internal_samplerate); + extradata = av_malloc(5); + if (extradata == NULL) return AVERROR_NOMEM; - extradata_size = cds; - - for(i = 0; i < 3; i++){ - *cdp++ = s[i] >> 8; - *cdp++ = s[i] & 0xff; - memcpy(cdp, p, s[i]); - cdp += s[i]; - p += s[i]; - cps -= s[i]; + extradata[0] = (profile << 3) | ((sri&0x0E) >> 1); + extradata[1] = ((sri&0x01) << 7) | (audiotrack->channels<<3); + if (strstr(track->codec_id, "SBR")) { + sri = matroska_aac_sri(audiotrack->samplerate); + extradata[2] = 0x56; + extradata[3] = 0xE5; + extradata[4] = 0x80 | (sri<<3); + extradata_size = 5; + } else { + extradata_size = 2; } + } - codec_id = CODEC_ID_VORBIS; - } else if (!strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_MPEG2) || - !strcmp(track->codec_id, - MATROSKA_CODEC_ID_AUDIO_MPEG4)) - codec_id = CODEC_ID_AAC; - else - codec_id = CODEC_ID_NONE; + else if (codec_id == CODEC_ID_TTA) { + MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track; + ByteIOContext b; + extradata_size = 30; + extradata = av_mallocz(extradata_size); + if (extradata == NULL) + return AVERROR_NOMEM; + init_put_byte(&b, extradata, extradata_size, 1, + NULL, NULL, NULL, NULL); + put_buffer(&b, (uint8_t *) "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); + } + + 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->flags |= MATROSKA_TRACK_REAL_V; + } if (codec_id == CODEC_ID_NONE) { av_log(matroska->ctx, AV_LOG_INFO, @@ -2302,55 +2301,58 @@ matroska_read_header (AVFormatContext *s, st = av_new_stream(s, track->stream_index); if (st == NULL) return AVERROR_NOMEM; - av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */ + av_set_pts_info(st, 64, matroska->time_scale, 1000*1000*1000); /* 64 bit pts in ns */ - st->codec.codec_id = codec_id; + st->codec->codec_id = codec_id; + + if (track->default_duration) + av_reduce(&st->codec->time_base.num, &st->codec->time_base.den, + track->default_duration, 1000000000, 30000); if(extradata){ - st->codec.extradata = extradata; - st->codec.extradata_size = extradata_size; + 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); - if(st->codec.extradata == NULL) + st->codec->extradata = av_malloc(track->codec_priv_size); + if(st->codec->extradata == NULL) return AVERROR_NOMEM; - st->codec.extradata_size = track->codec_priv_size; - memcpy(st->codec.extradata, track->codec_priv, + st->codec->extradata_size = track->codec_priv_size; + memcpy(st->codec->extradata,track->codec_priv+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; + 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) - st->codec.sample_aspect_ratio.num = - videotrack->pixel_width; - else - st->codec.sample_aspect_ratio.num = - videotrack->display_width; + videotrack->display_width= videotrack->pixel_width; if (videotrack->display_height == 0) - st->codec.sample_aspect_ratio.num = - videotrack->pixel_height; - else - st->codec.sample_aspect_ratio.num = - videotrack->display_height; - + videotrack->display_height= videotrack->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, + 255); } 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->codec_type = CODEC_TYPE_AUDIO; + st->codec->sample_rate = audiotrack->samplerate; + st->codec->channels = audiotrack->channels; + } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { + st->codec->codec_type = CODEC_TYPE_SUBTITLE; } /* What do we do with private data? E.g. for Vorbis. */ } + res = 0; } - return 0; + return res; } static int @@ -2366,194 +2368,227 @@ matroska_find_track_by_num (MatroskaDemuxContext *matroska, return -1; } +static inline int +rv_offset(uint8_t *data, int slice, int slices) +{ + return AV_RL32(data+8*slice+4) + 8*slices; +} + static int -matroska_parse_blockgroup (MatroskaDemuxContext *matroska, - uint64_t cluster_time) +matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size, + int64_t pos, uint64_t cluster_time, + int is_keyframe, int *ptrack, AVPacket **ppkt) { int res = 0; - uint32_t id; + int track; AVPacket *pkt; - int is_keyframe = PKT_FLAG_KEY, last_num_packets = matroska->num_packets; + uint8_t *origdata = data; + int16_t block_time; + uint32_t *lace_size = NULL; + int n, flags, laces = 0; + uint64_t num; + + /* first byte(s): tracknum */ + if ((n = matroska_ebmlnum_uint(data, size, &num)) < 0) { + av_log(matroska->ctx, AV_LOG_ERROR, "EBML block data error\n"); + av_free(origdata); + return res; + } + data += n; + size -= n; - av_log(matroska->ctx, AV_LOG_DEBUG, "parsing blockgroup...\n"); + /* fetch track from num */ + track = matroska_find_track_by_num(matroska, num); + if (ptrack) *ptrack = track; + if (size <= 3 || track < 0 || track >= matroska->num_tracks) { + av_log(matroska->ctx, AV_LOG_INFO, + "Invalid stream %d or size %u\n", track, size); + av_free(origdata); + return res; + } + if(matroska->ctx->streams[ matroska->tracks[track]->stream_index ]->discard >= AVDISCARD_ALL){ + av_free(origdata); + return res; + } - while (res == 0) { - if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { - res = AVERROR_IO; - break; - } else if (matroska->level_up) { - matroska->level_up--; + /* block_time (relative to cluster time) */ + block_time = (data[0] << 8) | data[1]; + data += 2; + size -= 2; + flags = *data; + data += 1; + size -= 1; + if (is_keyframe == -1) + is_keyframe = flags & 1 ? PKT_FLAG_KEY : 0; + switch ((flags & 0x06) >> 1) { + case 0x0: /* no lacing */ + laces = 1; + lace_size = av_mallocz(sizeof(int)); + lace_size[0] = size; break; - } - switch (id) { - /* one block inside the group. Note, block parsing is one - * of the harder things, so this code is a bit complicated. - * See http://www.matroska.org/ for documentation. */ - case MATROSKA_ID_BLOCK: { - uint8_t *data, *origdata; - int size; - uint64_t time; - uint32_t *lace_size = NULL; - int n, track, flags, laces = 0; - uint64_t num; - - if ((res = ebml_read_binary(matroska, &id, &data, &size)) < 0) - break; - origdata = data; - - /* first byte(s): blocknum */ - if ((n = matroska_ebmlnum_uint(data, size, &num)) < 0) { - av_log(matroska->ctx, AV_LOG_ERROR, - "EBML block data error\n"); - av_free(origdata); + case 0x1: /* xiph lacing */ + case 0x2: /* fixed-size lacing */ + case 0x3: /* EBML lacing */ + if (size == 0) { + res = -1; + break; + } + laces = (*data) + 1; + data += 1; + size -= 1; + lace_size = av_mallocz(laces * sizeof(int)); + + switch ((flags & 0x06) >> 1) { + case 0x1: /* xiph lacing */ { + uint8_t temp; + uint32_t total = 0; + for (n = 0; res == 0 && n < laces - 1; n++) { + while (1) { + if (size == 0) { + res = -1; + break; + } + temp = *data; + lace_size[n] += temp; + data += 1; + size -= 1; + if (temp != 0xff) + break; + } + total += lace_size[n]; + } + lace_size[n] = size - total; break; } - data += n; - size -= n; - /* fetch track from num */ - track = matroska_find_track_by_num(matroska, num); - if (size <= 3 || track < 0 || track >= matroska->num_tracks) { - av_log(matroska->ctx, AV_LOG_INFO, - "Invalid stream %d or size %u\n", track, size); - av_free(origdata); + case 0x2: /* fixed-size lacing */ + for (n = 0; n < laces; n++) + lace_size[n] = size / laces; break; - } - if(matroska->ctx->streams[ matroska->tracks[track]->stream_index ]->discard){ - av_free(origdata); - break; - } - /* time (relative to cluster time) */ - time = ((data[0] << 8) | data[1]) * matroska->time_scale; - data += 2; - size -= 2; - flags = *data; - data += 1; - size -= 1; - switch ((flags & 0x06) >> 1) { - case 0x0: /* no lacing */ - laces = 1; - lace_size = av_mallocz(sizeof(int)); - lace_size[0] = size; + case 0x3: /* EBML lacing */ { + uint32_t total; + n = matroska_ebmlnum_uint(data, size, &num); + if (n < 0) { + av_log(matroska->ctx, AV_LOG_INFO, + "EBML block data error\n"); break; - - case 0x1: /* xiph lacing */ - case 0x2: /* fixed-size lacing */ - case 0x3: /* EBML lacing */ - if (size == 0) { - res = -1; + } + data += n; + size -= n; + total = lace_size[0] = num; + for (n = 1; res == 0 && n < laces - 1; n++) { + int64_t snum; + int r; + r = matroska_ebmlnum_sint (data, size, &snum); + if (r < 0) { + av_log(matroska->ctx, AV_LOG_INFO, + "EBML block data error\n"); break; } - laces = (*data) + 1; - data += 1; - size -= 1; - lace_size = av_mallocz(laces * sizeof(int)); - - switch ((flags & 0x06) >> 1) { - case 0x1: /* xiph lacing */ { - uint8_t temp; - uint32_t total = 0; - for (n = 0; res == 0 && n < laces - 1; n++) { - while (1) { - if (size == 0) { - res = -1; - break; - } - temp = *data; - lace_size[n] += temp; - data += 1; - size -= 1; - if (temp != 0xff) - break; - } - total += lace_size[n]; - } - lace_size[n] = size - total; - break; - } + data += r; + size -= r; + lace_size[n] = lace_size[n - 1] + snum; + total += lace_size[n]; + } + lace_size[n] = size - total; + break; + } + } + break; + } - case 0x2: /* fixed-size lacing */ - for (n = 0; n < laces; n++) - lace_size[n] = size / laces; - break; + if (res == 0) { + int real_v = matroska->tracks[track]->flags & MATROSKA_TRACK_REAL_V; + for (n = 0; n < laces; n++) { + uint64_t timecode = AV_NOPTS_VALUE; + int slice, slices = 1; - case 0x3: /* EBML lacing */ { - uint32_t total; - n = matroska_ebmlnum_uint(data, size, &num); - if (n < 0) { - av_log(matroska->ctx, AV_LOG_INFO, - "EBML block data error\n"); - break; - } - data += n; - size -= n; - total = lace_size[0] = num; - for (n = 1; res == 0 && n < laces - 1; n++) { - int64_t snum; - int r; - r = matroska_ebmlnum_sint (data, size, - &snum); - if (r < 0) { - av_log(matroska->ctx, AV_LOG_INFO, - "EBML block data error\n"); - break; - } - data += r; - size -= r; - lace_size[n] = lace_size[n - 1] + snum; - total += lace_size[n]; - } - lace_size[n] = size - total; - break; - } - } - break; + if (real_v) { + slices = *data++ + 1; + lace_size[n]--; + } + if (cluster_time != (uint64_t)-1 && n == 0) { + if (cluster_time + block_time >= 0) + timecode = (cluster_time + block_time) * matroska->time_scale; + } + /* FIXME: duration */ + + for (slice=0; slicedata, data+slice_offset, slice_size); - if (res == 0) { - for (n = 0; n < laces; n++) { - uint64_t timecode = 0; + if (n == 0) + pkt->flags = is_keyframe; + pkt->stream_index = matroska->tracks[track]->stream_index; - pkt = av_mallocz(sizeof(AVPacket)); - /* XXX: prevent data copy... */ - if (av_new_packet(pkt,lace_size[n]) < 0) { - res = AVERROR_NOMEM; - break; - } - if (cluster_time != (uint64_t)-1) { - if (time < 0 && (-time) > cluster_time) - timecode = cluster_time; - else - timecode = cluster_time + time; - } - /* FIXME: duration */ + pkt->pts = timecode; + pkt->pos = pos; + + matroska_queue_packet(matroska, pkt); + } + data += lace_size[n]; + } + } - memcpy(pkt->data, data, lace_size[n]); - data += lace_size[n]; - if (n == 0) - pkt->flags = is_keyframe; - pkt->stream_index = - matroska->tracks[track]->stream_index; + av_free(lace_size); + av_free(origdata); + return res; +} - pkt->pts = timecode / 1000000; /* ns to ms */ +static int +matroska_parse_blockgroup (MatroskaDemuxContext *matroska, + uint64_t cluster_time) +{ + int res = 0; + uint32_t id; + AVPacket *pkt = NULL; + int is_keyframe = PKT_FLAG_KEY, last_num_packets = matroska->num_packets; + uint64_t duration = AV_NOPTS_VALUE; + int track = -1; + uint8_t *data; + int size = 0; + int64_t pos = 0; - matroska_queue_packet(matroska, pkt); - } - } + av_log(matroska->ctx, AV_LOG_DEBUG, "parsing blockgroup...\n"); + + while (res == 0) { + if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { + res = AVERROR_IO; + break; + } else if (matroska->level_up) { + matroska->level_up--; + break; + } - av_free(lace_size); - av_free(origdata); + switch (id) { + /* one block inside the group. Note, block parsing is one + * of the harder things, so this code is a bit complicated. + * See http://www.matroska.org/ for documentation. */ + case MATROSKA_ID_BLOCK: { + pos = url_ftell(&matroska->ctx->pb); + res = ebml_read_binary(matroska, &id, &data, &size); break; } case MATROSKA_ID_BLOCKDURATION: { - uint64_t num; - if ((res = ebml_read_uint(matroska, &id, &num)) < 0) + if ((res = ebml_read_uint(matroska, &id, &duration)) < 0) break; - av_log(matroska->ctx, AV_LOG_INFO, - "FIXME: implement support for BlockDuration\n"); break; } @@ -2582,6 +2617,21 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska, } } + if (res) + return res; + + if (size > 0) + res = matroska_parse_block(matroska, data, size, pos, cluster_time, + is_keyframe, &track, &pkt); + + if (pkt) + { + if (duration != AV_NOPTS_VALUE) + pkt->duration = duration; + else if (track >= 0 && track < matroska->num_tracks) + pkt->duration = matroska->tracks[track]->default_duration / matroska->time_scale; + } + return res; } @@ -2591,9 +2641,12 @@ matroska_parse_cluster (MatroskaDemuxContext *matroska) int res = 0; uint32_t id; uint64_t cluster_time = 0; + uint8_t *data; + int64_t pos; + int size; av_log(matroska->ctx, AV_LOG_DEBUG, - "parsing cluster at %lld\n", url_ftell(&matroska->ctx->pb)); + "parsing cluster at %"PRId64"\n", url_ftell(&matroska->ctx->pb)); while (res == 0) { if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { @@ -2610,7 +2663,7 @@ matroska_parse_cluster (MatroskaDemuxContext *matroska) uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; - cluster_time = num * matroska->time_scale; + cluster_time = num; break; } @@ -2621,6 +2674,14 @@ matroska_parse_cluster (MatroskaDemuxContext *matroska) res = matroska_parse_blockgroup(matroska, cluster_time); break; + case MATROSKA_ID_SIMPLEBLOCK: + pos = url_ftell(&matroska->ctx->pb); + res = ebml_read_binary(matroska, &id, &data, &size); + if (res == 0) + res = matroska_parse_block(matroska, data, size, pos, + cluster_time, -1, NULL, NULL); + break; + default: av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%x in cluster data\n", id); @@ -2648,47 +2709,46 @@ matroska_read_packet (AVFormatContext *s, int res = 0; uint32_t id; - /* Do we still have a packet queued? */ - if (matroska_deliver_packet(matroska, pkt) == 0) - return 0; + /* Read stream until we have a packet queued. */ + while (matroska_deliver_packet(matroska, pkt)) { - /* Have we already reached the end? */ - if (matroska->done) - return AVERROR_IO; + /* Have we already reached the end? */ + if (matroska->done) + return AVERROR_IO; - while (res == 0) { - if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { - res = AVERROR_IO; - break; - } else if (matroska->level_up) { - matroska->level_up--; - break; - } + while (res == 0) { + if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { + return AVERROR_IO; + } else if (matroska->level_up) { + matroska->level_up--; + break; + } - switch (id) { - case MATROSKA_ID_CLUSTER: - if ((res = ebml_read_master(matroska, &id)) < 0) + switch (id) { + case MATROSKA_ID_CLUSTER: + if ((res = ebml_read_master(matroska, &id)) < 0) + break; + if ((res = matroska_parse_cluster(matroska)) == 0) + res = 1; /* Parsed one cluster, let's get out. */ break; - if ((res = matroska_parse_cluster(matroska)) == 0) - res = 1; /* Parsed one cluster, let's get out. */ - break; - default: - case EBML_ID_VOID: - res = ebml_read_skip(matroska); + default: + case EBML_ID_VOID: + res = ebml_read_skip(matroska); + break; + } + + if (matroska->level_up) { + matroska->level_up--; break; + } } - if (matroska->level_up) { - matroska->level_up--; - break; - } + if (res == -1) + matroska->done = 1; } - if (res == -1) - matroska->done = 1; - - return matroska_deliver_packet(matroska, pkt); + return 0; } static int @@ -2697,12 +2757,9 @@ matroska_read_close (AVFormatContext *s) MatroskaDemuxContext *matroska = s->priv_data; int n = 0; - if (matroska->writing_app) - av_free(matroska->writing_app); - if (matroska->muxing_app) - av_free(matroska->muxing_app); - if (matroska->index) - av_free(matroska->index); + av_free(matroska->writing_app); + av_free(matroska->muxing_app); + av_free(matroska->index); if (matroska->packets != NULL) { for (n = 0; n < matroska->num_packets; n++) { @@ -2714,30 +2771,19 @@ matroska_read_close (AVFormatContext *s) for (n = 0; n < matroska->num_tracks; n++) { MatroskaTrack *track = matroska->tracks[n]; - if (track->codec_id) - av_free(track->codec_id); - if (track->codec_name) - av_free(track->codec_name); - if (track->codec_priv) - av_free(track->codec_priv); - if (track->name) - av_free(track->name); - if (track->language) - av_free(track->language); + av_free(track->codec_id); + av_free(track->codec_name); + av_free(track->codec_priv); + av_free(track->name); + av_free(track->language); av_free(track); } - for (n = 0; n < s->nb_streams; n++) { - av_free(s->streams[n]->codec.extradata); - } - - memset(matroska, 0, sizeof(MatroskaDemuxContext)); - return 0; } -static AVInputFormat matroska_iformat = { +AVInputFormat matroska_demuxer = { "matroska", "Matroska file format", sizeof(MatroskaDemuxContext), @@ -2746,10 +2792,3 @@ static AVInputFormat matroska_iformat = { matroska_read_packet, matroska_read_close, }; - -int -matroska_init(void) -{ - av_register_input_format(&matroska_iformat); - return 0; -}