Esempio n. 1
0
static int w64_read_header(AVFormatContext *s)
{
    int64_t size;
    AVIOContext *pb  = s->pb;
    WAVDemuxContext    *wav = s->priv_data;
    AVStream *st;
    uint8_t guid[16];
    int ret;

    avio_read(pb, guid, 16);
    if (memcmp(guid, guid_riff, 16))
        return -1;

    if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) /* riff + wave + fmt + sizes */
        return -1;

    avio_read(pb, guid, 16);
    if (memcmp(guid, guid_wave, 16)) {
        av_log(s, AV_LOG_ERROR, "could not find wave guid\n");
        return -1;
    }

    size = find_guid(pb, guid_fmt);
    if (size < 0) {
        av_log(s, AV_LOG_ERROR, "could not find fmt guid\n");
        return -1;
    }

    st = avformat_new_stream(s, NULL);
    if (!st)
        return AVERROR(ENOMEM);

    /* subtract chunk header size - normal wav file doesn't count it */
    ret = ff_get_wav_header(pb, st->codec, size - 24);
    if (ret < 0)
        return ret;
    avio_skip(pb, FFALIGN(size, INT64_C(8)) - size);

    handle_stream_probing(st);
    st->need_parsing = AVSTREAM_PARSE_FULL_RAW;

    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);

    size = find_guid(pb, guid_data);
    if (size < 0) {
        av_log(s, AV_LOG_ERROR, "could not find data guid\n");
        return -1;
    }
    wav->data_end = avio_tell(pb) + size - 24;
    wav->w64      = 1;

    return 0;
}
Esempio n. 2
0
static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
{
    AVIOContext *pb = s->pb;
    int ret;

    /* parse fmt header */
    *st = avformat_new_stream(s, NULL);
    if (!*st)
        return AVERROR(ENOMEM);

    ret = ff_get_wav_header(pb, (*st)->codec, size);
    if (ret < 0)
        return ret;
    handle_stream_probing(*st);

    (*st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;

    avpriv_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate);

    return 0;
}
Esempio n. 3
0
static int w64_read_header(AVFormatContext *s)
{
    int64_t size, data_ofs = 0;
    AVIOContext *pb      = s->pb;
    WAVDemuxContext *wav = s->priv_data;
    AVStream *st;
    uint8_t guid[16];
    int ret;

    avio_read(pb, guid, 16);
    if (memcmp(guid, ff_w64_guid_riff, 16))
        return AVERROR_INVALIDDATA;

    /* riff + wave + fmt + sizes */
    if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8)
        return AVERROR_INVALIDDATA;

    avio_read(pb, guid, 16);
    if (memcmp(guid, ff_w64_guid_wave, 16)) {
        av_log(s, AV_LOG_ERROR, "could not find wave guid\n");
        return AVERROR_INVALIDDATA;
    }

    wav->w64 = 1;

    st = avformat_new_stream(s, NULL);
    if (!st)
        return AVERROR(ENOMEM);

    while (!url_feof(pb)) {
        if (avio_read(pb, guid, 16) != 16)
            break;
        size = avio_rl64(pb);
        if (size <= 24 || INT64_MAX - size < avio_tell(pb))
            return AVERROR_INVALIDDATA;

        if (!memcmp(guid, ff_w64_guid_fmt, 16)) {
            /* subtract chunk header size - normal wav file doesn't count it */
            ret = ff_get_wav_header(pb, st->codec, size - 24);
            if (ret < 0)
                return ret;
            avio_skip(pb, FFALIGN(size, INT64_C(8)) - size);

            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
        } else if (!memcmp(guid, ff_w64_guid_fact, 16)) {
            int64_t samples;

            samples = avio_rl64(pb);
            if (samples > 0)
                st->duration = samples;
        } else if (!memcmp(guid, ff_w64_guid_data, 16)) {
            wav->data_end = avio_tell(pb) + size - 24;

            data_ofs = avio_tell(pb);
            if (!pb->seekable)
                break;

            avio_skip(pb, size - 24);
        } else if (!memcmp(guid, ff_w64_guid_summarylist, 16)) {
            int64_t start, end, cur;
            uint32_t count, chunk_size, i;

            start = avio_tell(pb);
            end = start + size;
            count = avio_rl32(pb);

            for (i = 0; i < count; i++) {
                char chunk_key[5], *value;

                if (url_feof(pb) || (cur = avio_tell(pb)) < 0 || cur > end - 8 /* = tag + size */)
                    break;

                chunk_key[4] = 0;
                avio_read(pb, chunk_key, 4);
                chunk_size = avio_rl32(pb);

                value = av_mallocz(chunk_size + 1);
                if (!value)
                    return AVERROR(ENOMEM);

                ret = avio_get_str16le(pb, chunk_size, value, chunk_size);
                avio_skip(pb, chunk_size - ret);

                av_dict_set(&s->metadata, chunk_key, value, AV_DICT_DONT_STRDUP_VAL);
            }

            avio_skip(pb, end - avio_tell(pb));
        } else {
            av_log(s, AV_LOG_DEBUG, "unknown guid: "FF_PRI_GUID"\n", FF_ARG_GUID(guid));
            avio_skip(pb, size - 24);
        }
    }

    if (!data_ofs)
        return AVERROR_EOF;

    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);

    handle_stream_probing(st);
    st->need_parsing = AVSTREAM_PARSE_FULL_RAW;

    avio_seek(pb, data_ofs, SEEK_SET);

    return 0;
}