From 9a742826443afd72c238d4920fe82cbbb0ce8007 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 28 Dec 2012 13:40:55 +0000 Subject: [PATCH] Sony Wave64 muxer Signed-off-by: Paul B Mahol --- Changelog | 1 + configure | 1 + doc/general.texi | 2 +- libavformat/Makefile | 3 +- libavformat/allformats.c | 2 +- libavformat/version.h | 2 +- libavformat/w64.c | 33 ++++++++++++++++ libavformat/w64.h | 29 ++++++++++++++ libavformat/wavdec.c | 27 ++++--------- libavformat/wavenc.c | 84 ++++++++++++++++++++++++++++++++++++++++ tests/fate/avformat.mak | 1 + tests/lavf-regression.sh | 4 ++ tests/ref/lavf/w64 | 3 ++ 13 files changed, 169 insertions(+), 23 deletions(-) create mode 100644 libavformat/w64.c create mode 100644 libavformat/w64.h create mode 100644 tests/ref/lavf/w64 diff --git a/Changelog b/Changelog index ab7232552e..b0a0de5237 100644 --- a/Changelog +++ b/Changelog @@ -51,6 +51,7 @@ version : - pp (postproc) filter ported from MPlayer - NIST Sphere demuxer - MPL2, VPlayer, MPlayer, AQTitle, PJS and SubViewer v1 subtitles demuxers and decoders +- Sony Wave64 muxer version 1.0: diff --git a/configure b/configure index ea36a5454a..faea887399 100755 --- a/configure +++ b/configure @@ -1899,6 +1899,7 @@ tg2_muxer_select="mov_muxer" tgp_muxer_select="mov_muxer" vobsub_demuxer_select="mpegps_demuxer" w64_demuxer_deps="wav_demuxer" +w64_muxer_deps="wav_muxer" # indevs / outdevs alsa_indev_deps="alsa_asoundlib_h snd_pcm_htimestamp" diff --git a/doc/general.texi b/doc/general.texi index ea513ff13a..542d7e28c7 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -374,7 +374,7 @@ library: @item Sony OpenMG (OMA) @tab X @tab X @tab Audio format used in Sony Sonic Stage and Sony Vegas. @item Sony PlayStation STR @tab @tab X -@item Sony Wave64 (W64) @tab @tab X +@item Sony Wave64 (W64) @tab X @tab X @item SoX native format @tab X @tab X @item SUN AU format @tab X @tab X @item Text files @tab @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index d77b3bd09e..ae3e60d9f5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -372,7 +372,8 @@ OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc.o OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o OBJS-$(CONFIG_VPLAYER_DEMUXER) += vplayerdec.o OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o -OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o pcm.o +OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o w64.o pcm.o +OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index b3455b53fe..bb8888bc1d 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -282,7 +282,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(VOC, voc); REGISTER_DEMUXER (VPLAYER, vplayer); REGISTER_DEMUXER (VQF, vqf); - REGISTER_DEMUXER (W64, w64); + REGISTER_MUXDEMUX(W64, w64); REGISTER_MUXDEMUX(WAV, wav); REGISTER_DEMUXER (WC3, wc3); REGISTER_MUXER (WEBM, webm); diff --git a/libavformat/version.h b/libavformat/version.h index 6fb42d84ed..00ce71dbe6 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,7 +30,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 54 -#define LIBAVFORMAT_VERSION_MINOR 57 +#define LIBAVFORMAT_VERSION_MINOR 58 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/w64.c b/libavformat/w64.c new file mode 100644 index 0000000000..0fff2f2e8b --- /dev/null +++ b/libavformat/w64.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2009 Daniel Verkamp + * + * 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 "w64.h" + +const uint8_t ff_w64_guid_riff[16] = { 'r', 'i', 'f', 'f', + 0x2E, 0x91, 0xCF, 0x11, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }; + +const uint8_t ff_w64_guid_wave[16] = { 'w', 'a', 'v', 'e', + 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; + +const uint8_t ff_w64_guid_fmt [16] = { 'f', 'm', 't', ' ', + 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; + +const uint8_t ff_w64_guid_data[16] = { 'd', 'a', 't', 'a', + 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; diff --git a/libavformat/w64.h b/libavformat/w64.h new file mode 100644 index 0000000000..7edba462f0 --- /dev/null +++ b/libavformat/w64.h @@ -0,0 +1,29 @@ +/* + * 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 + */ + +#ifndef AVFORMAT_W64_H +#define AVFORMAT_W64_H + +#include + +extern const uint8_t ff_w64_guid_riff[16]; +extern const uint8_t ff_w64_guid_wave[16]; +extern const uint8_t ff_w64_guid_fmt [16]; +extern const uint8_t ff_w64_guid_data[16]; + +#endif /* AVFORMAT_W64_H */ diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index 9d09865f4b..de140713ea 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -33,6 +33,7 @@ #include "avio_internal.h" #include "pcm.h" #include "riff.h" +#include "w64.h" #include "avio.h" #include "metadata.h" @@ -396,9 +397,6 @@ static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16]) return -1; } -static const uint8_t guid_data[16] = { 'd', 'a', 't', 'a', - 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; - #define MAX_SIZE 4096 static int wav_read_packet(AVFormatContext *s, @@ -455,7 +453,7 @@ smv_out: left= INT_MAX; if (left <= 0){ if (CONFIG_W64_DEMUXER && wav->w64) - left = find_guid(s->pb, guid_data) - 24; + left = find_guid(s->pb, ff_w64_guid_data) - 24; else left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a')); if (left < 0) { @@ -541,21 +539,12 @@ AVInputFormat ff_wav_demuxer = { #if CONFIG_W64_DEMUXER -static const uint8_t guid_riff[16] = { 'r', 'i', 'f', 'f', - 0x2E, 0x91, 0xCF, 0x11, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }; - -static const uint8_t guid_wave[16] = { 'w', 'a', 'v', 'e', - 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; - -static const uint8_t guid_fmt [16] = { 'f', 'm', 't', ' ', - 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; - static int w64_probe(AVProbeData *p) { if (p->buf_size <= 40) return 0; - if (!memcmp(p->buf, guid_riff, 16) && - !memcmp(p->buf + 24, guid_wave, 16)) + if (!memcmp(p->buf, ff_w64_guid_riff, 16) && + !memcmp(p->buf + 24, ff_w64_guid_wave, 16)) return AVPROBE_SCORE_MAX; else return 0; @@ -571,19 +560,19 @@ static int w64_read_header(AVFormatContext *s) int ret; avio_read(pb, guid, 16); - if (memcmp(guid, guid_riff, 16)) + if (memcmp(guid, ff_w64_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)) { + if (memcmp(guid, ff_w64_guid_wave, 16)) { av_log(s, AV_LOG_ERROR, "could not find wave guid\n"); return -1; } - size = find_guid(pb, guid_fmt); + size = find_guid(pb, ff_w64_guid_fmt); if (size < 0) { av_log(s, AV_LOG_ERROR, "could not find fmt guid\n"); return -1; @@ -604,7 +593,7 @@ static int w64_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); - size = find_guid(pb, guid_data); + size = find_guid(pb, ff_w64_guid_data); if (size < 0) { av_log(s, AV_LOG_ERROR, "could not find data guid\n"); return -1; diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index 5a4b085764..79e3713a9b 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -2,6 +2,9 @@ * WAV muxer * Copyright (c) 2001, 2002 Fabrice Bellard * + * Sony Wave64 muxer + * Copyright (c) 2012 Paul B Mahol + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -43,6 +46,7 @@ typedef struct WAVMuxContext { int write_bext; } WAVMuxContext; +#if CONFIG_WAV_MUXER static inline void bwf_write_bext_string(AVFormatContext *s, const char *key, int maxlen) { AVDictionaryEntry *tag; @@ -218,3 +222,83 @@ AVOutputFormat ff_wav_muxer = { .codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 }, .priv_class = &wav_muxer_class, }; +#endif /* CONFIG_WAV_MUXER */ + +#if CONFIG_W64_MUXER +#include "w64.h" + +static void start_guid(AVIOContext *pb, const uint8_t *guid, int64_t *pos) +{ + *pos = avio_tell(pb); + + avio_write(pb, guid, 16); + avio_wl64(pb, INT64_MAX); +} + +static void end_guid(AVIOContext *pb, int64_t start) +{ + int64_t end, pos = avio_tell(pb); + + end = FFALIGN(pos, 8); + ffio_fill(pb, 0, end - pos); + avio_seek(pb, start + 16, SEEK_SET); + avio_wl64(pb, end - start); + avio_seek(pb, end, SEEK_SET); +} + +static int w64_write_header(AVFormatContext *s) +{ + WAVMuxContext *wav = s->priv_data; + AVIOContext *pb = s->pb; + int64_t start; + int ret; + + avio_write(pb, ff_w64_guid_riff, sizeof(ff_w64_guid_riff)); + avio_wl64(pb, -1); + avio_write(pb, ff_w64_guid_wave, sizeof(ff_w64_guid_wave)); + start_guid(pb, ff_w64_guid_fmt, &start); + if ((ret = ff_put_wav_header(pb, s->streams[0]->codec)) < 0) { + av_log(s, AV_LOG_ERROR, "%s codec not supported\n", + s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE"); + return ret; + } + end_guid(pb, start); + start_guid(pb, ff_w64_guid_data, &wav->data); + + return 0; +} + +static int w64_write_trailer(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + WAVMuxContext *wav = s->priv_data; + int64_t file_size; + + if (pb->seekable) { + end_guid(pb, wav->data); + + file_size = avio_tell(pb); + avio_seek(pb, 16, SEEK_SET); + avio_wl64(pb, file_size); + avio_seek(pb, file_size, SEEK_SET); + + avio_flush(pb); + } + + return 0; +} + +AVOutputFormat ff_w64_muxer = { + .name = "w64", + .long_name = NULL_IF_CONFIG_SMALL("Sony Wave64"), + .extensions = "w64", + .priv_data_size = sizeof(WAVMuxContext), + .audio_codec = AV_CODEC_ID_PCM_S16LE, + .video_codec = AV_CODEC_ID_NONE, + .write_header = w64_write_header, + .write_packet = wav_write_packet, + .write_trailer = w64_write_trailer, + .flags = AVFMT_TS_NONSTRICT, + .codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 }, +}; +#endif /* CONFIG_W64_MUXER */ diff --git a/tests/fate/avformat.mak b/tests/fate/avformat.mak index 3528e55d9b..86fb071b80 100644 --- a/tests/fate/avformat.mak +++ b/tests/fate/avformat.mak @@ -45,6 +45,7 @@ FATE_LAVF-$(call ENCDEC2, MPEG2VIDEO, MP2, MPEGTS) += ts FATE_LAVF-$(call ENCDEC, PCM_U8, VOC) += voc FATE_LAVF-$(call ENCDEC, PCM_S16LE, VOC) += voc_s16 FATE_LAVF-$(call ENCDEC, PCM_S16LE, WAV) += wav +FATE_LAVF-$(call ENCMUX, PCM_S16LE, W64) += w64 FATE_LAVF-$(call ENCDEC, MP2, WTV) += wtv FATE_LAVF-$(call ENCDEC, XBM, IMAGE2) += xbm FATE_LAVF-$(call ENCDEC, XWD, IMAGE2) += xwd diff --git a/tests/lavf-regression.sh b/tests/lavf-regression.sh index 4afc29ae10..cc21f8d33e 100755 --- a/tests/lavf-regression.sh +++ b/tests/lavf-regression.sh @@ -334,6 +334,10 @@ if [ -n "$do_ircam" ] ; then do_audio_only ircam fi +if [ -n "$do_w64" ] ; then +do_audio_only w64 +fi + # pix_fmt conversions if [ -n "$do_pixfmt" ] ; then diff --git a/tests/ref/lavf/w64 b/tests/ref/lavf/w64 new file mode 100644 index 0000000000..9acda831e7 --- /dev/null +++ b/tests/ref/lavf/w64 @@ -0,0 +1,3 @@ +420bf38762386ae2ba8bf2e85b6cc7f2 *./tests/data/lavf/lavf.w64 +90224 ./tests/data/lavf/lavf.w64 +./tests/data/lavf/lavf.w64 CRC=0xf1ae5536