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

📄 matroskadec.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 5 页
字号:


/*
 * Put one packet in an application-supplied AVPacket struct.
 * Returns 0 on success or -1 on failure.
 */

static int
matroska_deliver_packet (MatroskaDemuxContext *matroska,
                         AVPacket             *pkt)
{
    if (matroska->num_packets > 0) {
        memcpy(pkt, matroska->packets[0], sizeof(AVPacket));
        av_free(matroska->packets[0]);
        if (matroska->num_packets > 1) {
            memmove(&matroska->packets[0], &matroska->packets[1],
                    (matroska->num_packets - 1) * sizeof(AVPacket *));
            matroska->packets =
                av_realloc(matroska->packets, (matroska->num_packets - 1) *
                           sizeof(AVPacket *));
        } else {
            av_freep(&matroska->packets);
        }
        matroska->num_packets--;
        return 0;
    }

    return -1;
}

/*
 * Put a packet into our internal queue. Will be delivered to the
 * user/application during the next get_packet() call.
 */

static void
matroska_queue_packet (MatroskaDemuxContext *matroska,
                       AVPacket             *pkt)
{
    matroska->packets =
        av_realloc(matroska->packets, (matroska->num_packets + 1) *
                   sizeof(AVPacket *));
    matroska->packets[matroska->num_packets] = pkt;
    matroska->num_packets++;
}


/*
 * Autodetecting...
 */

static int
matroska_probe (AVProbeData *p)
{
    uint64_t total = 0;
    int len_mask = 0x80, size = 1, n = 1;
    uint8_t probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' };

    /* ebml header? */
    if (AV_RB32(p->buf) != EBML_ID_HEADER)
        return 0;

    /* length of header */
    total = p->buf[4];
    while (size <= 8 && !(total & len_mask)) {
        size++;
        len_mask >>= 1;
    }
    if (size > 8)
      return 0;
    total &= (len_mask - 1);
    while (n < size)
        total = (total << 8) | p->buf[4 + n++];

    /* does the probe data contain the whole header? */
    if (p->buf_size < 4 + size + total)
      return 0;

    /* the header must contain the document type 'matroska'. For now,
     * 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++)
        if (!memcmp (&p->buf[n], probe_data, sizeof(probe_data)))
            return AVPROBE_SCORE_MAX;

    return 0;
}

/*
 * From here on, it's all XML-style DTD stuff... Needs no comments.
 */

static int
matroska_parse_info (MatroskaDemuxContext *matroska)
{
    int res = 0;
    uint32_t id;

    av_log(matroska->ctx, AV_LOG_DEBUG, "Parsing info...\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) {
            /* cluster timecode */
            case MATROSKA_ID_TIMECODESCALE: {
                uint64_t num;
                if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
                    break;
                matroska->time_scale = num;
                break;
            }

            case MATROSKA_ID_DURATION: {
                double num;
                if ((res = ebml_read_float(matroska, &id, &num)) < 0)
                    break;
                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;
            }

            case MATROSKA_ID_WRITINGAPP: {
                char *text;
                if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
                    break;
                matroska->writing_app = text;
                break;
            }

            case MATROSKA_ID_MUXINGAPP: {
                char *text;
                if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
                    break;
                matroska->muxing_app = text;
                break;
            }

            case MATROSKA_ID_DATEUTC: {
                int64_t time;
                if ((res = ebml_read_date(matroska, &id, &time)) < 0)
                    break;
                matroska->created = time;
                break;
            }

            default:
                av_log(matroska->ctx, AV_LOG_INFO,
                       "Unknown entry 0x%x in info 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_add_stream (MatroskaDemuxContext *matroska)
{
    int res = 0;
    uint32_t id;
    MatroskaTrack *track;

    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(MAX_TRACK_SIZE);
    matroska->num_tracks++;
    strcpy(track->language, "eng");

    /* start with the master */
    if ((res = ebml_read_master(matroska, &id)) < 0)
        return res;

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

        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 = 0;
                        break;
                }
                matroska->tracks[matroska->num_tracks - 1] = track;
                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;
                            if (num)
                                track->flags |=
                                    MATROSKA_VIDEOTRACK_INTERLACED;
                            else
                                track->flags &=
                                    ~MATROSKA_VIDEOTRACK_INTERLACED;
                            break;
                        }

                        /* stereo mode (whether the video has two streams,
                         * where one is for the left eye and the other for
                         * the right eye, which creates a 3D-like
                         * effect) */
                        case MATROSKA_ID_VIDEOSTEREOMODE: {
                            uint64_t num;
                            if ((res = ebml_read_uint(matroska, &id,
                                                      &num)) < 0)
                                break;
                            if (num != MATROSKA_EYE_MODE_MONO &&
                                num != MATROSKA_EYE_MODE_LEFT &&
                                num != MATROSKA_EYE_MODE_RIGHT &&
                                num != MATROSKA_EYE_MODE_BOTH) {
                                av_log(matroska->ctx, AV_LOG_INFO,
                                       "Ignoring unknown eye mode 0x%x\n",
                                       (uint32_t) num);
                                break;
                            }
                            videotrack->eye_mode = num;
                            break;
                        }

                        /* aspect ratio behaviour */
                        case MATROSKA_ID_VIDEOASPECTRATIO: {
                            uint64_t num;
                            if ((res = ebml_read_uint(matroska, &id,
                                                      &num)) < 0)
                                break;
                            if (num != MATROSKA_ASPECT_RATIO_MODE_FREE &&
                                num != MATROSKA_ASPECT_RATIO_MODE_KEEP &&
                                num != MATROSKA_ASPECT_RATIO_MODE_FIXED) {
                                av_log(matroska->ctx, AV_LOG_INFO,
                                       "Ignoring unknown aspect ratio 0x%x\n",
                                       (uint32_t) num);
                                break;
                            }
                            videotrack->ar_mode = num;
                            break;
                        }

                        /* colourspace (only matters for raw video)
                         * fourcc */

⌨️ 快捷键说明

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