* commit 'a3a0af4fb1237bed0af75868073f9a63db8b1864': avutil: make aes and sha api public handle malloc failures in ff_get_wav_header add xWMA demuxer mpegts: force the default timebase libavcodec: Bump micro after adding the dtx AVOptions Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n0.8
| @@ -93,6 +93,7 @@ version <next>: | |||
| - fieldorder video filter added | |||
| - AAC encoding via libvo-aacenc | |||
| - AMR-WB encoding via libvo-amrwbenc | |||
| - xWMA demuxer | |||
| version 0.6: | |||
| @@ -259,6 +259,8 @@ library: | |||
| @tab Multimedia format used in Westwood Studios games. | |||
| @item Westwood Studios VQA @tab @tab X | |||
| @tab Multimedia format used in Westwood Studios games. | |||
| @item xWMA @tab @tab X | |||
| @tab Microsoft audio container used by XAudio 2. | |||
| @item YUV4MPEG pipe @tab X @tab X | |||
| @item Psygnosis YOP @tab @tab X | |||
| @end multitable | |||
| @@ -2,20 +2,20 @@ | |||
| * AAC encoder wrapper | |||
| * Copyright (c) 2010 Martin Storsjo | |||
| * | |||
| * This file is part of Libav. | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * Libav is free software; you can redistribute it and/or | |||
| * FFmpeg 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.1 of the License, or (at your option) any later version. | |||
| * | |||
| * Libav is distributed in the hope that it will be useful, | |||
| * FFmpeg 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 Libav; if not, write to the Free Software | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| @@ -2,20 +2,20 @@ | |||
| * AMR Audio encoder stub | |||
| * Copyright (c) 2003 the ffmpeg project | |||
| * | |||
| * This file is part of Libav. | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * Libav is free software; you can redistribute it and/or | |||
| * FFmpeg 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.1 of the License, or (at your option) any later version. | |||
| * | |||
| * Libav is distributed in the hope that it will be useful, | |||
| * FFmpeg 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 Libav; if not, write to the Free Software | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| @@ -22,7 +22,7 @@ | |||
| #define LIBAVCODEC_VERSION_MAJOR 52 | |||
| #define LIBAVCODEC_VERSION_MINOR 119 | |||
| #define LIBAVCODEC_VERSION_MICRO 0 | |||
| #define LIBAVCODEC_VERSION_MICRO 1 | |||
| #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | |||
| LIBAVCODEC_VERSION_MINOR, \ | |||
| @@ -302,6 +302,7 @@ OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood.o | |||
| OBJS-$(CONFIG_WTV_DEMUXER) += wtv.o asf.o asfdec.o mpegts.o riff.o | |||
| OBJS-$(CONFIG_WV_DEMUXER) += wv.o apetag.o | |||
| OBJS-$(CONFIG_XA_DEMUXER) += xa.o | |||
| OBJS-$(CONFIG_XWMA_DEMUXER) += xwma.o riff.o | |||
| OBJS-$(CONFIG_YOP_DEMUXER) += yop.o | |||
| OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o | |||
| OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o | |||
| @@ -227,6 +227,7 @@ void av_register_all(void) | |||
| REGISTER_DEMUXER (WTV, wtv); | |||
| REGISTER_DEMUXER (WV, wv); | |||
| REGISTER_DEMUXER (XA, xa); | |||
| REGISTER_DEMUXER (XWMA, xwma); | |||
| REGISTER_DEMUXER (YOP, yop); | |||
| REGISTER_MUXDEMUX (YUV4MPEGPIPE, yuv4mpegpipe); | |||
| @@ -280,7 +280,9 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) | |||
| st->codec->codec_type = type; | |||
| if (type == AVMEDIA_TYPE_AUDIO) { | |||
| ff_get_wav_header(pb, st->codec, type_specific_size); | |||
| int ret = ff_get_wav_header(pb, st->codec, type_specific_size); | |||
| if (ret < 0) | |||
| return ret; | |||
| if (is_dvr_ms_audio) { | |||
| // codec_id and codec_tag are unreliable in dvr_ms | |||
| // files. Set them later by probing stream. | |||
| @@ -345,6 +345,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| int avih_width=0, avih_height=0; | |||
| int amv_file_format=0; | |||
| uint64_t list_end = 0; | |||
| int ret; | |||
| avi->stream_index= -1; | |||
| @@ -623,7 +624,9 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| // avio_skip(pb, size - 5 * 4); | |||
| break; | |||
| case AVMEDIA_TYPE_AUDIO: | |||
| ff_get_wav_header(pb, st->codec, size); | |||
| ret = ff_get_wav_header(pb, st->codec, size); | |||
| if (ret < 0) | |||
| return ret; | |||
| ast->dshow_block_align= st->codec->block_align; | |||
| if(ast->sample_size && st->codec->block_align && ast->sample_size != st->codec->block_align){ | |||
| av_log(s, AV_LOG_WARNING, "sample size (%d) != block align (%d)\n", ast->sample_size, st->codec->block_align); | |||
| @@ -60,6 +60,7 @@ static int dxa_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| int w, h; | |||
| int num, den; | |||
| int flags; | |||
| int ret; | |||
| tag = avio_rl32(pb); | |||
| if (tag != MKTAG('D', 'E', 'X', 'A')) | |||
| @@ -102,7 +103,9 @@ static int dxa_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| ast = av_new_stream(s, 0); | |||
| if (!ast) | |||
| return -1; | |||
| ff_get_wav_header(pb, ast->codec, fsize); | |||
| ret = ff_get_wav_header(pb, ast->codec, fsize); | |||
| if (ret < 0) | |||
| return ret; | |||
| // find 'data' chunk | |||
| while(avio_tell(pb) < c->vidpos && !url_feof(pb)){ | |||
| tag = avio_rl32(pb); | |||
| @@ -1332,9 +1332,12 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| } else if (!strcmp(track->codec_id, "A_MS/ACM") | |||
| && track->codec_priv.size >= 14 | |||
| && track->codec_priv.data != NULL) { | |||
| int ret; | |||
| ffio_init_context(&b, track->codec_priv.data, track->codec_priv.size, | |||
| AVIO_RDONLY, NULL, NULL, NULL, NULL); | |||
| ff_get_wav_header(&b, st->codec, track->codec_priv.size); | |||
| ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size); | |||
| if (ret < 0) | |||
| return ret; | |||
| codec_id = st->codec->codec_id; | |||
| extradata_offset = FFMIN(track->codec_priv.size, 18); | |||
| } else if (!strcmp(track->codec_id, "V_QUICKTIME") | |||
| @@ -479,6 +479,7 @@ static int mpegts_write_header(AVFormatContext *s) | |||
| /* assign pids to each stream */ | |||
| for(i = 0;i < s->nb_streams; i++) { | |||
| st = s->streams[i]; | |||
| av_set_pts_info(st, 33, 1, 90000); | |||
| ts_st = av_mallocz(sizeof(MpegTSWriteStream)); | |||
| if (!ts_st) | |||
| goto fail; | |||
| @@ -488,7 +488,7 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *t | |||
| * WAVEFORMATEX adds 'WORD cbSize' and basically makes itself | |||
| * an openended structure. | |||
| */ | |||
| void ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) | |||
| int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) | |||
| { | |||
| int id; | |||
| @@ -531,6 +531,8 @@ void ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) | |||
| codec->extradata_size = cbSize; | |||
| if (cbSize > 0) { | |||
| codec->extradata = av_mallocz(codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); | |||
| if (!codec->extradata) | |||
| return AVERROR(ENOMEM); | |||
| avio_read(pb, codec->extradata, codec->extradata_size); | |||
| size -= cbSize; | |||
| } | |||
| @@ -544,6 +546,8 @@ void ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) | |||
| codec->channels = 0; | |||
| codec->sample_rate = 0; | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -45,7 +45,7 @@ int ff_get_bmp_header(AVIOContext *pb, AVStream *st); | |||
| void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *tags, int for_asf); | |||
| int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc); | |||
| enum CodecID ff_wav_codec_get_id(unsigned int tag, int bps); | |||
| void ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size); | |||
| int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size); | |||
| extern const AVCodecTag ff_codec_bmp_tags[]; | |||
| extern const AVCodecTag ff_codec_wav_tags[]; | |||
| @@ -24,7 +24,7 @@ | |||
| #include "libavutil/avutil.h" | |||
| #define LIBAVFORMAT_VERSION_MAJOR 52 | |||
| #define LIBAVFORMAT_VERSION_MINOR 107 | |||
| #define LIBAVFORMAT_VERSION_MINOR 108 | |||
| #define LIBAVFORMAT_VERSION_MICRO 0 | |||
| #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | |||
| @@ -195,6 +195,7 @@ static int wav_read_header(AVFormatContext *s, | |||
| AVIOContext *pb = s->pb; | |||
| AVStream *st; | |||
| WAVContext *wav = s->priv_data; | |||
| int ret; | |||
| /* check RIFF header */ | |||
| tag = avio_rl32(pb); | |||
| @@ -227,7 +228,9 @@ static int wav_read_header(AVFormatContext *s, | |||
| if (!st) | |||
| return AVERROR(ENOMEM); | |||
| ff_get_wav_header(pb, st->codec, size); | |||
| ret = ff_get_wav_header(pb, st->codec, size); | |||
| if (ret < 0) | |||
| return ret; | |||
| st->need_parsing = AVSTREAM_PARSE_FULL; | |||
| av_set_pts_info(st, 64, 1, st->codec->sample_rate); | |||
| @@ -383,6 +386,7 @@ static int w64_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| WAVContext *wav = s->priv_data; | |||
| AVStream *st; | |||
| uint8_t guid[16]; | |||
| int ret; | |||
| avio_read(pb, guid, 16); | |||
| if (memcmp(guid, guid_riff, 16)) | |||
| @@ -408,7 +412,9 @@ static int w64_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| return AVERROR(ENOMEM); | |||
| /* subtract chunk header size - normal wav file doesn't count it */ | |||
| ff_get_wav_header(pb, st->codec, size - 24); | |||
| ret = ff_get_wav_header(pb, st->codec, size - 24); | |||
| if (ret < 0) | |||
| return ret; | |||
| avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); | |||
| st->need_parsing = AVSTREAM_PARSE_FULL; | |||
| @@ -645,7 +645,9 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, | |||
| if (!st) | |||
| return NULL; | |||
| if (!ff_guidcmp(formattype, format_waveformatex)) { | |||
| ff_get_wav_header(pb, st->codec, size); | |||
| int ret = ff_get_wav_header(pb, st->codec, size); | |||
| if (ret < 0) | |||
| return NULL; | |||
| } else { | |||
| if (ff_guidcmp(formattype, format_none)) | |||
| av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype)); | |||
| @@ -0,0 +1,257 @@ | |||
| /* | |||
| * xWMA demuxer | |||
| * Copyright (c) 2011 Max Horn | |||
| * | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg 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.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg 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 FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "avformat.h" | |||
| #include "riff.h" | |||
| /* | |||
| * Demuxer for xWMA, a Microsoft audio container used by XAudio 2. | |||
| */ | |||
| typedef struct { | |||
| int64_t data_end; | |||
| } XWMAContext; | |||
| static int xwma_probe(AVProbeData *p) | |||
| { | |||
| if (!memcmp(p->buf, "RIFF", 4) && !memcmp(p->buf + 8, "XWMA", 4)) | |||
| return AVPROBE_SCORE_MAX; | |||
| return 0; | |||
| } | |||
| static int xwma_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| { | |||
| int64_t size, av_uninit(data_size); | |||
| int ret; | |||
| uint32_t dpds_table_size = 0; | |||
| uint32_t *dpds_table = 0; | |||
| unsigned int tag; | |||
| AVIOContext *pb = s->pb; | |||
| AVStream *st; | |||
| XWMAContext *xwma = s->priv_data; | |||
| int i; | |||
| /* The following code is mostly copied from wav.c, with some | |||
| * minor alterations. | |||
| */ | |||
| /* check RIFF header */ | |||
| tag = avio_rl32(pb); | |||
| if (tag != MKTAG('R', 'I', 'F', 'F')) | |||
| return -1; | |||
| avio_rl32(pb); /* file size */ | |||
| tag = avio_rl32(pb); | |||
| if (tag != MKTAG('X', 'W', 'M', 'A')) | |||
| return -1; | |||
| /* parse fmt header */ | |||
| tag = avio_rl32(pb); | |||
| if (tag != MKTAG('f', 'm', 't', ' ')) | |||
| return -1; | |||
| size = avio_rl32(pb); | |||
| st = av_new_stream(s, 0); | |||
| if (!st) | |||
| return AVERROR(ENOMEM); | |||
| ret = ff_get_wav_header(pb, st->codec, size); | |||
| if (ret < 0) | |||
| return ret; | |||
| st->need_parsing = AVSTREAM_PARSE_NONE; | |||
| /* All xWMA files I have seen contained WMAv2 data. If there are files | |||
| * using WMA Pro or some other codec, then we need to figure out the right | |||
| * extradata for that. Thus, ask the user for feedback, but try to go on | |||
| * anyway. | |||
| */ | |||
| if (st->codec->codec_id != CODEC_ID_WMAV2) { | |||
| av_log(s, AV_LOG_WARNING, "unexpected codec (tag 0x04%x; id %d)\n", | |||
| st->codec->codec_tag, st->codec->codec_id); | |||
| av_log_ask_for_sample(s, NULL); | |||
| } else { | |||
| /* In all xWMA files I have seen, there is no extradata. But the WMA | |||
| * codecs require extradata, so we provide our own fake extradata. | |||
| * | |||
| * First, check that there really was no extradata in the header. If | |||
| * there was, then try to use, after asking the the user to provide a | |||
| * sample of this unusual file. | |||
| */ | |||
| if (st->codec->extradata_size != 0) { | |||
| /* Surprise, surprise: We *did* get some extradata. No idea | |||
| * if it will work, but just go on and try it, after asking | |||
| * the user for a sample. | |||
| */ | |||
| av_log(s, AV_LOG_WARNING, "unexpected extradata (%d bytes)\n", | |||
| st->codec->extradata_size); | |||
| av_log_ask_for_sample(s, NULL); | |||
| } else { | |||
| st->codec->extradata_size = 6; | |||
| st->codec->extradata = av_mallocz(6 + FF_INPUT_BUFFER_PADDING_SIZE); | |||
| if (!st->codec->extradata) | |||
| return AVERROR(ENOMEM); | |||
| /* setup extradata with our experimentally obtained value */ | |||
| st->codec->extradata[4] = 31; | |||
| } | |||
| } | |||
| /* set the sample rate */ | |||
| av_set_pts_info(st, 64, 1, st->codec->sample_rate); | |||
| /* parse the remaining RIFF chunks */ | |||
| for (;;) { | |||
| if (pb->eof_reached) | |||
| return -1; | |||
| /* read next chunk tag */ | |||
| tag = avio_rl32(pb); | |||
| size = avio_rl32(pb); | |||
| if (tag == MKTAG('d', 'a', 't', 'a')) { | |||
| /* We assume that the data chunk comes last. */ | |||
| break; | |||
| } else if (tag == MKTAG('d','p','d','s')) { | |||
| /* Quoting the MSDN xWMA docs on the dpds chunk: "Contains the | |||
| * decoded packet cumulative data size array, each element is the | |||
| * number of bytes accumulated after the corresponding xWMA packet | |||
| * is decoded in order" | |||
| * | |||
| * Each packet has size equal to st->codec->block_align, which in | |||
| * all cases I saw so far was always 2230. Thus, we can use the | |||
| * dpds data to compute a seeking index. | |||
| */ | |||
| /* Error out if there is more than one dpds chunk. */ | |||
| if (dpds_table) { | |||
| av_log(s, AV_LOG_ERROR, "two dpds chunks present\n"); | |||
| return -1; | |||
| } | |||
| /* Compute the number of entries in the dpds chunk. */ | |||
| if (size & 3) { /* Size should be divisible by four */ | |||
| av_log(s, AV_LOG_WARNING, "dpds chunk size "PRId64" not divisible by 4\n", size); | |||
| } | |||
| dpds_table_size = size / 4; | |||
| if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) { | |||
| av_log(s, AV_LOG_ERROR, "dpds chunk size "PRId64" invalid\n", size); | |||
| return -1; | |||
| } | |||
| /* Allocate some temporary storage to keep the dpds data around. | |||
| * for processing later on. | |||
| */ | |||
| dpds_table = av_malloc(dpds_table_size * sizeof(uint32_t)); | |||
| if (!dpds_table) { | |||
| return AVERROR(ENOMEM); | |||
| } | |||
| for (i = 0; i < dpds_table_size; ++i) { | |||
| dpds_table[i] = avio_rl32(pb); | |||
| size -= 4; | |||
| } | |||
| } | |||
| avio_skip(pb, size); | |||
| } | |||
| /* Determine overall data length */ | |||
| if (size < 0) | |||
| return -1; | |||
| if (!size) { | |||
| xwma->data_end = INT64_MAX; | |||
| } else | |||
| xwma->data_end = avio_tell(pb) + size; | |||
| if (dpds_table && dpds_table_size) { | |||
| int64_t cur_pos; | |||
| const uint32_t bytes_per_sample | |||
| = (st->codec->channels * st->codec->bits_per_coded_sample) >> 3; | |||
| /* Estimate the duration from the total number of output bytes. */ | |||
| const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1]; | |||
| st->duration = total_decoded_bytes / bytes_per_sample; | |||
| /* Use the dpds data to build a seek table. We can only do this after | |||
| * we know the offset to the data chunk, as we need that to determine | |||
| * the actual offset to each input block. | |||
| * Note: If we allowed ourselves to assume that the data chunk always | |||
| * follows immediately after the dpds block, we could of course guess | |||
| * the data block's start offset already while reading the dpds chunk. | |||
| * I decided against that, just in case other chunks ever are | |||
| * discovered. | |||
| */ | |||
| cur_pos = avio_tell(pb); | |||
| for (i = 0; i < dpds_table_size; ++i) { | |||
| /* From the number of output bytes that would accumulate in the | |||
| * output buffer after decoding the first (i+1) packets, we compute | |||
| * an offset / timestamp pair. | |||
| */ | |||
| av_add_index_entry(st, | |||
| cur_pos + (i+1) * st->codec->block_align, /* pos */ | |||
| dpds_table[i] / bytes_per_sample, /* timestamp */ | |||
| st->codec->block_align, /* size */ | |||
| 0, /* duration */ | |||
| AVINDEX_KEYFRAME); | |||
| } | |||
| } else if (st->codec->bit_rate) { | |||
| /* No dpds chunk was present (or only an empty one), so estimate | |||
| * the total duration using the average bits per sample and the | |||
| * total data length. | |||
| */ | |||
| st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate; | |||
| } | |||
| av_free(dpds_table); | |||
| return 0; | |||
| } | |||
| static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt) | |||
| { | |||
| int ret, size; | |||
| int64_t left; | |||
| AVStream *st; | |||
| XWMAContext *xwma = s->priv_data; | |||
| st = s->streams[0]; | |||
| left = xwma->data_end - avio_tell(s->pb); | |||
| if (left <= 0) { | |||
| return AVERROR_EOF; | |||
| } | |||
| /* read a single block; the default block size is 2230. */ | |||
| size = (st->codec->block_align > 1) ? st->codec->block_align : 2230; | |||
| size = FFMIN(size, left); | |||
| ret = av_get_packet(s->pb, pkt, size); | |||
| if (ret < 0) | |||
| return ret; | |||
| pkt->stream_index = 0; | |||
| return ret; | |||
| } | |||
| AVInputFormat ff_xwma_demuxer = { | |||
| "xwma", | |||
| NULL_IF_CONFIG_SMALL("Microsoft xWMA"), | |||
| sizeof(XWMAContext), | |||
| xwma_probe, | |||
| xwma_read_header, | |||
| xwma_read_packet, | |||
| }; | |||