⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 matroska.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Matroska file demuxer (no muxer yet) * Copyright (c) 2003-2004 The ffmpeg Project * * This library 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. * * This library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file matroska.c * Matroska file demuxer * by Ronald Bultje <rbultje@ronald.bitfreak.net> * with a little help from Moritz Bunkus <moritz@bunkus.org> * Specs available on the matroska project page: * http://www.matroska.org/. */#include "avformat.h"/* For codec_get_bmp_id and codec_get_wav_id. */#include "avi.h"#include "intfloat_readwrite.h"/* EBML version supported */#define EBML_VERSION 1/* top-level master-IDs */#define EBML_ID_HEADER             0x1A45DFA3/* IDs in the HEADER master */#define EBML_ID_EBMLVERSION        0x4286#define EBML_ID_EBMLREADVERSION    0x42F7#define EBML_ID_EBMLMAXIDLENGTH    0x42F2#define EBML_ID_EBMLMAXSIZELENGTH  0x42F3#define EBML_ID_DOCTYPE            0x4282#define EBML_ID_DOCTYPEVERSION     0x4287#define EBML_ID_DOCTYPEREADVERSION 0x4285/* general EBML types */#define EBML_ID_VOID               0xEC/* * Matroska element IDs. max. 32-bit. *//* toplevel segment */#define MATROSKA_ID_SEGMENT    0x18538067/* matroska top-level master IDs */#define MATROSKA_ID_INFO       0x1549A966#define MATROSKA_ID_TRACKS     0x1654AE6B#define MATROSKA_ID_CUES       0x1C53BB6B#define MATROSKA_ID_TAGS       0x1254C367#define MATROSKA_ID_SEEKHEAD   0x114D9B74#define MATROSKA_ID_CLUSTER    0x1F43B675/* IDs in the info master */#define MATROSKA_ID_TIMECODESCALE 0x2AD7B1#define MATROSKA_ID_DURATION   0x4489#define MATROSKA_ID_WRITINGAPP 0x5741#define MATROSKA_ID_MUXINGAPP  0x4D80#define MATROSKA_ID_DATEUTC    0x4461/* ID in the tracks master */#define MATROSKA_ID_TRACKENTRY 0xAE/* IDs in the trackentry master */#define MATROSKA_ID_TRACKNUMBER 0xD7#define MATROSKA_ID_TRACKUID   0x73C5#define MATROSKA_ID_TRACKTYPE  0x83#define MATROSKA_ID_TRACKAUDIO 0xE1#define MATROSKA_ID_TRACKVIDEO 0xE0#define MATROSKA_ID_CODECID    0x86#define MATROSKA_ID_CODECPRIVATE 0x63A2#define MATROSKA_ID_CODECNAME  0x258688#define MATROSKA_ID_CODECINFOURL 0x3B4040#define MATROSKA_ID_CODECDOWNLOADURL 0x26B240#define MATROSKA_ID_TRACKNAME  0x536E#define MATROSKA_ID_TRACKLANGUAGE 0x22B59C#define MATROSKA_ID_TRACKFLAGENABLED 0xB9#define MATROSKA_ID_TRACKFLAGDEFAULT 0x88#define MATROSKA_ID_TRACKFLAGLACING 0x9C#define MATROSKA_ID_TRACKMINCACHE 0x6DE7#define MATROSKA_ID_TRACKMAXCACHE 0x6DF8#define MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383/* IDs in the trackvideo master */#define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3#define MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0#define MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA#define MATROSKA_ID_VIDEOPIXELWIDTH 0xB0#define MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA#define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A#define MATROSKA_ID_VIDEOSTEREOMODE 0x53B9#define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3#define MATROSKA_ID_VIDEOCOLOURSPACE 0x2EB524/* IDs in the trackaudio master */#define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5#define MATROSKA_ID_AUDIOBITDEPTH 0x6264#define MATROSKA_ID_AUDIOCHANNELS 0x9F/* ID in the cues master */#define MATROSKA_ID_POINTENTRY 0xBB/* IDs in the pointentry master */#define MATROSKA_ID_CUETIME    0xB3#define MATROSKA_ID_CUETRACKPOSITION 0xB7/* IDs in the cuetrackposition master */#define MATROSKA_ID_CUETRACK   0xF7#define MATROSKA_ID_CUECLUSTERPOSITION 0xF1/* IDs in the tags master *//* TODO *//* IDs in the seekhead master */#define MATROSKA_ID_SEEKENTRY  0x4DBB/* IDs in the seekpoint master */#define MATROSKA_ID_SEEKID     0x53AB#define MATROSKA_ID_SEEKPOSITION 0x53AC/* IDs in the cluster master */#define MATROSKA_ID_CLUSTERTIMECODE 0xE7#define MATROSKA_ID_BLOCKGROUP 0xA0/* IDs in the blockgroup master */#define MATROSKA_ID_BLOCK      0xA1#define MATROSKA_ID_BLOCKDURATION 0x9B#define MATROSKA_ID_BLOCKREFERENCE 0xFBtypedef enum {  MATROSKA_TRACK_TYPE_VIDEO    = 0x1,  MATROSKA_TRACK_TYPE_AUDIO    = 0x2,  MATROSKA_TRACK_TYPE_COMPLEX  = 0x3,  MATROSKA_TRACK_TYPE_LOGO     = 0x10,  MATROSKA_TRACK_TYPE_SUBTITLE = 0x11,  MATROSKA_TRACK_TYPE_CONTROL  = 0x20,} MatroskaTrackType;typedef enum {  MATROSKA_EYE_MODE_MONO  = 0x0,  MATROSKA_EYE_MODE_RIGHT = 0x1,  MATROSKA_EYE_MODE_LEFT  = 0x2,  MATROSKA_EYE_MODE_BOTH  = 0x3,} MatroskaEyeMode;typedef enum {  MATROSKA_ASPECT_RATIO_MODE_FREE  = 0x0,  MATROSKA_ASPECT_RATIO_MODE_KEEP  = 0x1,  MATROSKA_ASPECT_RATIO_MODE_FIXED = 0x2,} MatroskaAspectRatioMode;/* * These aren't in any way "matroska-form" things, * it's just something I use in the muxer/demuxer. */typedef enum {  MATROSKA_TRACK_ENABLED = (1<<0),  MATROSKA_TRACK_DEFAULT = (1<<1),  MATROSKA_TRACK_LACING  = (1<<2),  MATROSKA_TRACK_SHIFT   = (1<<16)} MatroskaTrackFlags;typedef enum {  MATROSKA_VIDEOTRACK_INTERLACED = (MATROSKA_TRACK_SHIFT<<0)} MatroskaVideoTrackFlags;/* * Matroska Codec IDs. Strings. */typedef struct CodecTags{    char *str;    enum CodecID id;}CodecTags;#define MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC   "V_MS/VFW/FOURCC"#define MATROSKA_CODEC_ID_AUDIO_ACM          "A_MS/ACM"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 *///    {"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/MPEG2/"     , CODEC_ID_AAC},    {"A_AAC/MPEG4/"     , CODEC_ID_AAC},    {NULL               , CODEC_ID_NONE}/* TODO: AC3-9/10 (?), Real, Musepack, Quicktime */};/* max. depth in the EBML tree structure */#define EBML_MAX_DEPTH 16typedef struct Track {    MatroskaTrackType type;    /* Unique track number and track ID. stream_index is the index that     * the calling app uses for this track. */    uint32_t num,        uid,        stream_index;    char *name,        *language;    char *codec_id,        *codec_name;    unsigned char *codec_priv;    int codec_priv_size;    int64_t default_duration;    MatroskaTrackFlags flags;} MatroskaTrack;typedef struct MatroskaVideoTrack {    MatroskaTrack track;    int pixel_width,        pixel_height,        display_width,        display_height;    uint32_t fourcc;    MatroskaAspectRatioMode ar_mode;    MatroskaEyeMode eye_mode;    //..} MatroskaVideoTrack;typedef struct MatroskaAudioTrack {    MatroskaTrack track;    int channels,        bitdepth,        samplerate;    //..} MatroskaAudioTrack;typedef struct MatroskaSubtitleTrack {    MatroskaTrack track;    //..} MatroskaSubtitleTrack;typedef struct MatroskaLevel {    uint64_t start, length;} MatroskaLevel;typedef struct MatroskaDemuxIndex {  uint64_t        pos;   /* of the corresponding *cluster*! */  uint16_t        track; /* reference to 'num' */  uint64_t        time;  /* in nanoseconds */} MatroskaDemuxIndex;typedef struct MatroskaDemuxContext {    AVFormatContext *ctx;    /* ebml stuff */    int num_levels;    MatroskaLevel levels[EBML_MAX_DEPTH];    int level_up;    /* matroska stuff */    char *writing_app,        *muxing_app;    int64_t created;    /* timescale in the file */    int64_t time_scale;    /* 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). */    int num_tracks, num_streams;    MatroskaTrack *tracks[MAX_STREAMS];    /* cache for ID peeking */    uint32_t peek_id;    /* byte position of the segment inside the stream */    offset_t segment_start;    /* The packet queue. */    AVPacket **packets;    int num_packets;    /* have we already parse metadata/cues/clusters? */    int metadata_parsed,        index_parsed,        done;    /* The index for seeking. */    int num_indexes;    MatroskaDemuxIndex *index;} MatroskaDemuxContext;/* * The first few functions handle EBML file parsing. The rest * is the document interpretation. Matroska really just is a * EBML file. *//* * Return: the amount of levels in the hierarchy that the * current element lies higher than the previous one. * The opposite isn't done - that's auto-done using master * element reading. */static intebml_read_element_level_up (MatroskaDemuxContext *matroska){    ByteIOContext *pb = &matroska->ctx->pb;    offset_t pos = url_ftell(pb);    int num = 0;    while (matroska->num_levels > 0) {        MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1];        if (pos >= level->start + level->length) {            matroska->num_levels--;            num++;        } else {            break;        }    }    return num;}/* * Read: an "EBML number", which is defined as a variable-length * array of bytes. The first byte indicates the length by giving a * number of 0-bits followed by a one. The position of the first * "one" bit inside the first byte indicates the length of this * number. * Returns: num. of bytes read. < 0 on error. */static intebml_read_num (MatroskaDemuxContext *matroska,               int                   max_size,               uint64_t             *number){    ByteIOContext *pb = &matroska->ctx->pb;    int len_mask = 0x80, read = 1, n = 1;    int64_t total = 0;    /* the first byte tells us the length in bytes - get_byte() can normally     * return 0, but since that's not a valid first ebmlID byte, we can     * use it safely here to catch EOS. */    if (!(total = get_byte(pb))) {        /* we might encounter EOS here */        if (!url_feof(pb)) {            offset_t pos = url_ftell(pb);            av_log(matroska->ctx, AV_LOG_ERROR,                   "Read error at pos. %"PRIu64" (0x%"PRIx64")\n",                   pos, pos);        }        return AVERROR_IO; /* EOS or actual I/O error */    }    /* get the length of the EBML number */    while (read <= max_size && !(total & len_mask)) {        read++;        len_mask >>= 1;    }    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 %"PRIu64" (0x%"PRIx64")\n",               (uint8_t) total, pos, pos);        return AVERROR_INVALIDDATA;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -