]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/wav.c
use tapt atom for sample aspect ratio
[ffmpeg] / libavformat / wav.c
index f9163b46ee8f5b1f476d4366ad5b104bf519f303..a574b3b16f2f4b376390502741927d2791706a46 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2001, 2002 Fabrice Bellard
  *
  * Sony Wave64 demuxer
+ * RF64 demuxer
  * Copyright (c) 2009 Daniel Verkamp
  *
  * This file is part of FFmpeg.
@@ -22,7 +23,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "avformat.h"
-#include "raw.h"
+#include "avio_internal.h"
+#include "pcm.h"
 #include "riff.h"
 
 typedef struct {
@@ -38,12 +40,12 @@ typedef struct {
 static int wav_write_header(AVFormatContext *s)
 {
     WAVContext *wav = s->priv_data;
-    ByteIOContext *pb = s->pb;
+    AVIOContext *pb = s->pb;
     int64_t fmt, fact;
 
-    put_tag(pb, "RIFF");
-    put_le32(pb, 0); /* file length */
-    put_tag(pb, "WAVE");
+    ffio_wfourcc(pb, "RIFF");
+    avio_wl32(pb, 0); /* file length */
+    ffio_wfourcc(pb, "WAVE");
 
     /* format header */
     fmt = ff_start_tag(pb, "fmt ");
@@ -58,7 +60,7 @@ static int wav_write_header(AVFormatContext *s)
     if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
         && !url_is_streamed(s->pb)) {
         fact = ff_start_tag(pb, "fact");
-        put_le32(pb, 0);
+        avio_wl32(pb, 0);
         ff_end_tag(pb, fact);
     }
 
@@ -76,9 +78,9 @@ static int wav_write_header(AVFormatContext *s)
 
 static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    ByteIOContext *pb  = s->pb;
+    AVIOContext *pb  = s->pb;
     WAVContext    *wav = s->priv_data;
-    put_buffer(pb, pkt->data, pkt->size);
+    avio_write(pb, pkt->data, pkt->size);
     if(pkt->pts != AV_NOPTS_VALUE) {
         wav->minpts        = FFMIN(wav->minpts, pkt->pts);
         wav->maxpts        = FFMAX(wav->maxpts, pkt->pts);
@@ -90,17 +92,19 @@ static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
 
 static int wav_write_trailer(AVFormatContext *s)
 {
-    ByteIOContext *pb  = s->pb;
+    AVIOContext *pb  = s->pb;
     WAVContext    *wav = s->priv_data;
     int64_t file_size;
 
+    put_flush_packet(pb);
+
     if (!url_is_streamed(s->pb)) {
         ff_end_tag(pb, wav->data);
 
         /* update file size */
         file_size = url_ftell(pb);
         url_fseek(pb, 4, SEEK_SET);
-        put_le32(pb, (uint32_t)(file_size - 8));
+        avio_wl32(pb, (uint32_t)(file_size - 8));
         url_fseek(pb, file_size, SEEK_SET);
 
         put_flush_packet(pb);
@@ -112,7 +116,7 @@ static int wav_write_trailer(AVFormatContext *s)
                                            s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num,
                                            s->streams[0]->time_base.den);
             url_fseek(pb, wav->data-12, SEEK_SET);
-            put_le32(pb, number_of_samples);
+            avio_wl32(pb, number_of_samples);
             url_fseek(pb, file_size, SEEK_SET);
             put_flush_packet(pb);
         }
@@ -120,7 +124,7 @@ static int wav_write_trailer(AVFormatContext *s)
     return 0;
 }
 
-AVOutputFormat wav_muxer = {
+AVOutputFormat ff_wav_muxer = {
     "wav",
     NULL_IF_CONFIG_SMALL("WAV format"),
     "audio/x-wav",
@@ -137,8 +141,15 @@ AVOutputFormat wav_muxer = {
 
 
 #if CONFIG_WAV_DEMUXER
+
+static int64_t next_tag(AVIOContext *pb, unsigned int *tag)
+{
+    *tag = avio_rl32(pb);
+    return avio_rl32(pb);
+}
+
 /* return the size of the found tag */
-static int64_t find_tag(ByteIOContext *pb, uint32_t tag1)
+static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
 {
     unsigned int tag;
     int64_t size;
@@ -146,8 +157,7 @@ static int64_t find_tag(ByteIOContext *pb, uint32_t tag1)
     for (;;) {
         if (url_feof(pb))
             return -1;
-        tag  = get_le32(pb);
-        size = get_le32(pb);
+        size = next_tag(pb, &tag);
         if (tag == tag1)
             break;
         url_fseek(pb, size, SEEK_CUR);
@@ -160,40 +170,56 @@ static int wav_probe(AVProbeData *p)
     /* check file header */
     if (p->buf_size <= 32)
         return 0;
-    if (p->buf[ 0] == 'R' && p->buf[ 1] == 'I' &&
-        p->buf[ 2] == 'F' && p->buf[ 3] == 'F' &&
-        p->buf[ 8] == 'W' && p->buf[ 9] == 'A' &&
-        p->buf[10] == 'V' && p->buf[11] == 'E')
-        /*
-          Since ACT demuxer has standard WAV header at top of it's own,
-          returning score is decreased to avoid probe conflict
-          between ACT and WAV.
-        */
-        return AVPROBE_SCORE_MAX - 1;
-    else
-        return 0;
+    if (!memcmp(p->buf + 8, "WAVE", 4)) {
+        if (!memcmp(p->buf, "RIFF", 4))
+            /*
+              Since ACT demuxer has standard WAV header at top of it's own,
+              returning score is decreased to avoid probe conflict
+              between ACT and WAV.
+            */
+            return AVPROBE_SCORE_MAX - 1;
+        else if (!memcmp(p->buf,      "RF64", 4) &&
+                 !memcmp(p->buf + 12, "ds64", 4))
+            return AVPROBE_SCORE_MAX;
+    }
+    return 0;
 }
 
 /* wav input */
 static int wav_read_header(AVFormatContext *s,
                            AVFormatParameters *ap)
 {
-    int64_t size;
+    int64_t size, av_uninit(data_size);
+    int64_t sample_count=0;
+    int rf64;
     unsigned int tag;
-    ByteIOContext *pb = s->pb;
+    AVIOContext *pb = s->pb;
     AVStream *st;
     WAVContext *wav = s->priv_data;
 
     /* check RIFF header */
-    tag = get_le32(pb);
+    tag = avio_rl32(pb);
 
-    if (tag != MKTAG('R', 'I', 'F', 'F'))
+    rf64 = tag == MKTAG('R', 'F', '6', '4');
+    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
         return -1;
-    get_le32(pb); /* file size */
-    tag = get_le32(pb);
+    avio_rl32(pb); /* file size */
+    tag = avio_rl32(pb);
     if (tag != MKTAG('W', 'A', 'V', 'E'))
         return -1;
 
+    if (rf64) {
+        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
+            return -1;
+        size = avio_rl32(pb);
+        if (size < 16)
+            return -1;
+        avio_rl64(pb); /* RIFF size */
+        data_size = avio_rl64(pb);
+        sample_count = avio_rl64(pb);
+        url_fskip(pb, size - 16); /* skip rest of ds64 chunk */
+    }
+
     /* parse fmt header */
     size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
     if (size < 0)
@@ -207,24 +233,45 @@ static int wav_read_header(AVFormatContext *s,
 
     av_set_pts_info(st, 64, 1, st->codec->sample_rate);
 
-    size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
+    for (;;) {
+        if (url_feof(pb))
+            return -1;
+        size = next_tag(pb, &tag);
+        if (tag == MKTAG('d', 'a', 't', 'a')){
+            break;
+        }else if (tag == MKTAG('f','a','c','t') && !sample_count){
+            sample_count = avio_rl32(pb);
+            size -= 4;
+        }
+        url_fseek(pb, size, SEEK_CUR);
+    }
+    if (rf64)
+        size = data_size;
     if (size < 0)
         return -1;
-    wav->data_end= url_ftell(pb) + size;
+    if (!size) {
+        wav->data_end = INT64_MAX;
+    } else
+        wav->data_end= url_ftell(pb) + size;
+
+    if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
+        sample_count = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
+    if (sample_count)
+        st->duration = sample_count;
     return 0;
 }
 
 /** Find chunk with w64 GUID by skipping over other chunks
  * @return the size of the found chunk
  */
-static int64_t find_guid(ByteIOContext *pb, const uint8_t guid1[16])
+static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16])
 {
     uint8_t guid[16];
     int64_t size;
 
     while (!url_feof(pb)) {
-        get_buffer(pb, guid, 16);
-        size = get_le64(pb);
+        avio_read(pb, guid, 16);
+        size = avio_rl64(pb);
         if (size <= 24)
             return -1;
         if (!memcmp(guid, guid1, 16))
@@ -247,8 +294,6 @@ static int wav_read_packet(AVFormatContext *s,
     AVStream *st;
     WAVContext *wav = s->priv_data;
 
-    if (url_feof(s->pb))
-        return AVERROR(EIO);
     st = s->streams[0];
 
     left = wav->data_end - url_ftell(s->pb);
@@ -258,7 +303,7 @@ static int wav_read_packet(AVFormatContext *s,
         else
             left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a'));
         if (left < 0)
-            return AVERROR(EIO);
+            return AVERROR_EOF;
         wav->data_end= url_ftell(s->pb) + left;
     }
 
@@ -270,13 +315,10 @@ static int wav_read_packet(AVFormatContext *s,
     }
     size = FFMIN(size, left);
     ret  = av_get_packet(s->pb, pkt, size);
-    if (ret <= 0)
-        return AVERROR(EIO);
+    if (ret < 0)
+        return ret;
     pkt->stream_index = 0;
 
-    /* note: we need to modify the packet size here to handle the last
-       packet */
-    pkt->size = ret;
     return ret;
 }
 
@@ -299,7 +341,7 @@ static int wav_read_seek(AVFormatContext *s,
     return pcm_read_seek(s, stream_index, timestamp, flags);
 }
 
-AVInputFormat wav_demuxer = {
+AVInputFormat ff_wav_demuxer = {
     "wav",
     NULL_IF_CONFIG_SMALL("WAV format"),
     sizeof(WAVContext),
@@ -338,19 +380,19 @@ static int w64_probe(AVProbeData *p)
 static int w64_read_header(AVFormatContext *s, AVFormatParameters *ap)
 {
     int64_t size;
-    ByteIOContext *pb  = s->pb;
+    AVIOContext *pb  = s->pb;
     WAVContext    *wav = s->priv_data;
     AVStream *st;
     uint8_t guid[16];
 
-    get_buffer(pb, guid, 16);
+    avio_read(pb, guid, 16);
     if (memcmp(guid, guid_riff, 16))
         return -1;
 
-    if (get_le64(pb) < 16 + 8 + 16 + 8 + 16 + 8) /* riff + wave + fmt + sizes */
+    if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) /* riff + wave + fmt + sizes */
         return -1;
 
-    get_buffer(pb, guid, 16);
+    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;
@@ -385,7 +427,7 @@ static int w64_read_header(AVFormatContext *s, AVFormatParameters *ap)
     return 0;
 }
 
-AVInputFormat w64_demuxer = {
+AVInputFormat ff_w64_demuxer = {
     "w64",
     NULL_IF_CONFIG_SMALL("Sony Wave64 format"),
     sizeof(WAVContext),