matroskadec.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,000 行 · 第 1/5 页

C
2,000
字号
            matroska->level_up--;            break;        }        switch (id) {            /* one single index entry ('point') */            case MATROSKA_ID_POINTENTRY:                if ((res = ebml_read_master(matroska, &id)) < 0)                    break;                /* in the end, we hope to fill one entry with a                 * timestamp, a file position and a tracknum */                idx.pos   = (uint64_t) -1;                idx.time  = (uint64_t) -1;                idx.track = (uint16_t) -1;                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 single index entry ('point') */                        case MATROSKA_ID_CUETIME: {                            uint64_t time;                            if ((res = ebml_read_uint(matroska, &id,                                                      &time)) < 0)                                break;                            idx.time = time * matroska->time_scale;                            break;                        }                        /* position in the file + track to which it                         * belongs */                        case MATROSKA_ID_CUETRACKPOSITION:                            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) {                                    matroska->level_up--;                                    break;                                }                                switch (id) {                                    /* track number */                                    case MATROSKA_ID_CUETRACK: {                                        uint64_t num;                                        if ((res = ebml_read_uint(matroska,                                                          &id, &num)) < 0)                                            break;                                        idx.track = num;                                        break;                                    }                                        /* position in file */                                    case MATROSKA_ID_CUECLUSTERPOSITION: {                                        uint64_t num;                                        if ((res = ebml_read_uint(matroska,                                                          &id, &num)) < 0)                                            break;                                        idx.pos = num+matroska->segment_start;                                        break;                                    }                                    default:                                        av_log(matroska->ctx, AV_LOG_INFO,                                               "Unknown entry 0x%x in "                                               "CuesTrackPositions\n", id);                                        /* fall-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 entry 0x%x in cuespoint "                                   "index\n", id);                            /* fall-through */                        case EBML_ID_VOID:                            res = ebml_read_skip(matroska);                            break;                    }                    if (matroska->level_up) {                        matroska->level_up--;                        break;                    }                }                /* so let's see if we got what we wanted */                if (idx.pos   != (uint64_t) -1 &&                    idx.time  != (uint64_t) -1 &&                    idx.track != (uint16_t) -1) {                    if (matroska->num_indexes % 32 == 0) {                        /* re-allocate bigger index */                        matroska->index =                            av_realloc(matroska->index,                                       (matroska->num_indexes + 32) *                                       sizeof(MatroskaDemuxIndex));                    }                    matroska->index[matroska->num_indexes] = idx;                    matroska->num_indexes++;                }                break;            default:                av_log(matroska->ctx, AV_LOG_INFO,                       "Unknown entry 0x%x in cues header\n", id);                /* fall-through */            case EBML_ID_VOID:                res = ebml_read_skip(matroska);                break;        }        if (matroska->level_up) {            matroska->level_up--;            break;        }    }    return res;}static intmatroska_parse_metadata (MatroskaDemuxContext *matroska){    int res = 0;    uint32_t id;    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) {            /* Hm, this is unsupported... */            default:                av_log(matroska->ctx, AV_LOG_INFO,                       "Unknown entry 0x%x in metadata header\n", id);                /* fall-through */            case EBML_ID_VOID:                res = ebml_read_skip(matroska);                break;        }        if (matroska->level_up) {            matroska->level_up--;            break;        }    }    return res;}static intmatroska_parse_seekhead (MatroskaDemuxContext *matroska){    int res = 0;    uint32_t id;    av_log(matroska->ctx, AV_LOG_DEBUG, "parsing seekhead...\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) {            case MATROSKA_ID_SEEKENTRY: {                uint32_t seek_id = 0, peek_id_cache = 0;                uint64_t seek_pos = (uint64_t) -1, t;                int dummy_level = 0;                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) {                        matroska->level_up--;                        break;                    }                    switch (id) {                        case MATROSKA_ID_SEEKID:                            res = ebml_read_uint(matroska, &id, &t);                            seek_id = t;                            break;                        case MATROSKA_ID_SEEKPOSITION:                            res = ebml_read_uint(matroska, &id, &seek_pos);                            break;                        default:                            av_log(matroska->ctx, AV_LOG_INFO,                                   "Unknown seekhead ID 0x%x\n", id);                            /* fall-through */                        case EBML_ID_VOID:                            res = ebml_read_skip(matroska);                            break;                    }                    if (matroska->level_up) {                        matroska->level_up--;                        break;                    }                }                if (!seek_id || seek_pos == (uint64_t) -1) {                    av_log(matroska->ctx, AV_LOG_INFO,                           "Incomplete seekhead entry (0x%x/%"PRIu64")\n",                           seek_id, seek_pos);                    break;                }                switch (seek_id) {                    case MATROSKA_ID_CUES:                    case MATROSKA_ID_TAGS: {                        uint32_t level_up = matroska->level_up;                        offset_t before_pos;                        uint64_t length;                        MatroskaLevel level;                        /* remember the peeked ID and the current position */                        peek_id_cache = matroska->peek_id;                        before_pos = url_ftell(matroska->ctx->pb);                        /* seek */                        if ((res = ebml_read_seek(matroska, seek_pos +                                               matroska->segment_start)) < 0)                            goto finish;                        /* we don't want to lose our seekhead level, so we add                         * a dummy. This is a crude hack. */                        if (matroska->num_levels == EBML_MAX_DEPTH) {                            av_log(matroska->ctx, AV_LOG_INFO,                                   "Max EBML element depth (%d) reached, "                                   "cannot parse further.\n", EBML_MAX_DEPTH);                            return AVERROR_UNKNOWN;                        }                        level.start = 0;                        level.length = (uint64_t)-1;                        matroska->levels[matroska->num_levels] = level;                        matroska->num_levels++;                        dummy_level = 1;                        /* check ID */                        if (!(id = ebml_peek_id (matroska,                                                 &matroska->level_up)))                            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=%"PRIu64")",                                   seek_id, id, seek_pos +                                   matroska->segment_start);                            goto finish;                        }                        /* read master + parse */                        if ((res = ebml_read_master(matroska, &id)) < 0)                            goto finish;                        switch (id) {                            case MATROSKA_ID_CUES:                                if (!(res = matroska_parse_index(matroska)) ||                                    url_feof(matroska->ctx->pb)) {                                    matroska->index_parsed = 1;                                    res = 0;                                }                                break;                            case MATROSKA_ID_TAGS:                                if (!(res = matroska_parse_metadata(matroska)) ||                                   url_feof(matroska->ctx->pb)) {                                    matroska->metadata_parsed = 1;                                    res = 0;                                }                                break;                        }                    finish:                        /* remove dummy level */                        if (dummy_level)                            while (matroska->num_levels) {                                matroska->num_levels--;                                length =                                  matroska->levels[matroska->num_levels].length;                                if (length == (uint64_t)-1)                                    break;                            }                        /* seek back */                        if ((res = ebml_read_seek(matroska, before_pos)) < 0)                            return res;                        matroska->peek_id = peek_id_cache;                        matroska->level_up = level_up;                        break;                    }                    default:                        av_log(matroska->ctx, AV_LOG_INFO,                               "Ignoring seekhead entry for ID=0x%x\n",                               seek_id);                        break;                }                break;            }            default:                av_log(matroska->ctx, AV_LOG_INFO,                       "Unknown seekhead ID 0x%x\n", id);                /* fall-through */            case EBML_ID_VOID:                res = ebml_read_skip(matroska);                break;        }        if (matroska->level_up) {            matroska->level_up--;            break;        }    }    return res;}static intmatroska_parse_attachments(AVFormatContext *s){    MatroskaDemuxContext *matroska = s->priv_data;    int res = 0;    uint32_t id;    av_log(matroska->ctx, AV_LOG_DEBUG, "parsing attachments...\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) {        case MATROSKA_ID_ATTACHEDFILE: {            char* name = NULL;            char* mime = NULL;            uint8_t* data = NULL;            int i, data_size = 0;            AVStream *st;            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) {                    matroska->level_up--;                    break;                }                switch (

⌨️ 快捷键说明

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