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

📄 matroskadec.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 5 页
字号:
                    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 int
matroska_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 int
matroska_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;

                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)
                            return res;

                        /* 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++;

                        /* 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 */
                        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;
}

#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<ARRAY_SIZE(aac_profiles); profile++)
        if (strstr(codec_id, aac_profiles[profile]))
            break;
    return profile + 1;
}

static int
matroska_aac_sri (int samplerate)
{
    static const int aac_sample_rates[] = {
        96000, 88200, 64000, 48000, 44100, 32000,
        24000, 22050, 16000, 12000, 11025,  8000,
    };
    int sri;

    for (sri=0; sri<ARRAY_SIZE(aac_sample_rates); sri++)
        if (aac_sample_rates[sri] == samplerate)
            break;
    return sri;
}

static int
matroska_read_header (AVFormatContext    *s,
                      AVFormatParameters *ap)
{
    MatroskaDemuxContext *matroska = s->priv_data;
    char *doctype;
    int version, last_level, res = 0;
    uint32_t id;

    matroska->ctx = s;

    /* First read the EBML header. */
    doctype = NULL;
    if ((res = ebml_read_header(matroska, &doctype, &version)) < 0)
        return res;
    if ((doctype == NULL) || strcmp(doctype, "matroska")) {
        av_log(matroska->ctx, AV_LOG_ERROR,
               "Wrong EBML doctype ('%s' != 'matroska').\n",
               doctype ? doctype : "(none)");
        if (doctype)
            av_free(doctype);
        return AVERROR_NOFMT;
    }
    av_free(doctype);
    if (version > 2) {
        av_log(matroska->ctx, AV_LOG_ERROR,
               "Matroska demuxer version 2 too old for file version %d\n",
               version);
        return AVERROR_NOFMT;
    }

    /* The next thing is a segment. */
    while (1) {
        if (!(id = ebml_peek_id(matroska, &last_level)))
            return AVERROR(EIO);
        if (id == MATROSKA_ID_SEGMENT)
            break;

        /* oi! */
        av_log(matroska->ctx, AV_LOG_INFO,
               "Expected a Segment ID (0x%x), but received 0x%x!\n",
               MATROSKA_ID_SEGMENT, id);
        if ((res = ebml_read_skip(matroska)) < 0)
            return res;
    }

    /* We now have a Matroska segment.
     * Seeks are from the beginning of the segment,
     * after the segment ID/length. */
    if ((res = ebml_read_master(matroska, &id)) < 0)
        return res;
    matroska->segment_start = url_ftell(&s->pb);

    matroska->time_scale = 1000000;
    /* we've found our segment, start reading the different contents in here */
    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) {
            /* stream info */
            case MATROSKA_ID_INFO: {
                if ((res = ebml_read_master(matroska, &id)) < 0)
                    break;
                res = matroska_parse_info(matroska);
                break;
            }

            /* track info headers */
            case MATROSKA_ID_TRACKS: {
                if ((res = ebml_read_master(matroska, &id)) < 0)
                    break;
                res = matroska_parse_tracks(matroska);
                break;
            }

            /* stream index */
            case MATROSKA_ID_CUES: {
                if (!matroska->index_parsed) {
                    if ((res = ebml_read_master(matroska, &id)) < 0)
                        break;
                    res = matroska_parse_index(matroska);
                } else
                    res = ebml_read_skip(matroska);
                break;
            }

            /* metadata */
            case MATROSKA_ID_TAGS: {
                if (!matroska->metadata_parsed) {
                    if ((res = ebml_read_master(matroska, &id)) < 0)
                        break;
                    res = matroska_parse_metadata(matroska);
                } else
                    res = ebml_read_skip(matroska);
                break;
            }

            /* file index (if seekable, seek to Cues/Tags to parse it) */
            case MATROSKA_ID_SEEKHEAD: {
                if ((res = ebml_read_master(matroska, &id)) < 0)
                    break;
                res = matroska_parse_seekhead(matroska);
                break;
            }

            case MATROSKA_ID_CLUSTER: {
                /* Do not read the master - this will be done in the next
                 * call to matroska_read_packet. */
                res = 1;
                break;
            }

            default:
                av_log(matroska->ctx

⌨️ 快捷键说明

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