Merge commit '9d12dd6fa84d9f6094bdf0fdae62527ecec0bbb6'
[ffmpeg.git] / libavformat / qcp.c
index 6222bd5..b842e26 100644 (file)
  * @file
  * QCP format (.qcp) demuxer
  * @author Kenan Gillet
- * @sa RFC 3625: "The QCP File Format and Media Types for Speech Data"
+ * @see RFC 3625: "The QCP File Format and Media Types for Speech Data"
  *     http://tools.ietf.org/html/rfc3625
  */
 
+#include "libavutil/channel_layout.h"
 #include "libavutil/intreadwrite.h"
 #include "avformat.h"
+#include "riff.h"
 
-typedef struct {
+typedef struct QCPContext {
     uint32_t data_size;                     ///< size of data chunk
 
 #define QCP_MAX_MODE 4
@@ -55,6 +57,11 @@ static const uint8_t guid_evrc[16] = {
     0x91, 0xef, 0x73, 0x6a, 0x51, 0x00, 0xce, 0xb4
 };
 
+static const uint8_t guid_4gv[16] = {
+    0xca, 0x29, 0xfd, 0x3c, 0x53, 0xf6, 0xf5, 0x4e,
+    0x90, 0xe9, 0xf4, 0x23, 0x6d, 0x59, 0x9b, 0x61
+};
+
 /**
  * SMV GUID as stored in the file
  */
@@ -80,11 +87,11 @@ static int qcp_probe(AVProbeData *pd)
     return 0;
 }
 
-static int qcp_read_header(AVFormatContext *s, AVFormatParameters *ap)
+static int qcp_read_header(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
     QCPContext    *c  = s->priv_data;
-    AVStream      *st = av_new_stream(s, 0);
+    AVStream      *st = avformat_new_stream(s, NULL);
     uint8_t       buf[16];
     int           i, nb_rates;
 
@@ -92,31 +99,32 @@ static int qcp_read_header(AVFormatContext *s, AVFormatParameters *ap)
         return AVERROR(ENOMEM);
 
     avio_rb32(pb);                    // "RIFF"
-    s->file_size = avio_rl32(pb) + 8;
-    avio_seek(pb, 8 + 4 + 1 + 1, SEEK_CUR);    // "QLCMfmt " + chunk-size + major-version + minor-version
+    avio_skip(pb, 4 + 8 + 4 + 1 + 1);    // filesize + "QLCMfmt " + chunk-size + major-version + minor-version
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels   = 1;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels   = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     avio_read(pb, buf, 16);
     if (is_qcelp_13k_guid(buf)) {
-        st->codec->codec_id = CODEC_ID_QCELP;
+        st->codecpar->codec_id = AV_CODEC_ID_QCELP;
     } else if (!memcmp(buf, guid_evrc, 16)) {
-        av_log(s, AV_LOG_ERROR, "EVRC codec is not supported.\n");
-        return AVERROR_PATCHWELCOME;
+        st->codecpar->codec_id = AV_CODEC_ID_EVRC;
     } else if (!memcmp(buf, guid_smv, 16)) {
-        av_log(s, AV_LOG_ERROR, "SMV codec is not supported.\n");
-        return AVERROR_PATCHWELCOME;
+        st->codecpar->codec_id = AV_CODEC_ID_SMV;
+    } else if (!memcmp(buf, guid_4gv, 16)) {
+        st->codecpar->codec_id = AV_CODEC_ID_4GV;
     } else {
-        av_log(s, AV_LOG_ERROR, "Unknown codec GUID.\n");
+        av_log(s, AV_LOG_ERROR, "Unknown codec GUID "FF_PRI_GUID".\n",
+               FF_ARG_GUID(buf));
         return AVERROR_INVALIDDATA;
     }
-    avio_seek(pb, 2 + 80, SEEK_CUR); // codec-version + codec-name
-    st->codec->bit_rate = avio_rl16(pb);
+    avio_skip(pb, 2 + 80); // codec-version + codec-name
+    st->codecpar->bit_rate = avio_rl16(pb);
 
     s->packet_size = avio_rl16(pb);
-    avio_seek(pb, 2, SEEK_CUR); // block-size
-    st->codec->sample_rate = avio_rl16(pb);
-    avio_seek(pb, 2, SEEK_CUR); // sample-size
+    avio_skip(pb, 2); // block-size
+    st->codecpar->sample_rate = avio_rl16(pb);
+    avio_skip(pb, 2); // sample-size
 
     memset(c->rates_per_mode, -1, sizeof(c->rates_per_mode));
     nb_rates = avio_rl32(pb);
@@ -129,7 +137,7 @@ static int qcp_read_header(AVFormatContext *s, AVFormatParameters *ap)
         } else
             c->rates_per_mode[mode] = size;
     }
-    avio_seek(pb, 16 - 2*nb_rates + 20, SEEK_CUR); // empty entries of rate-map-table + reserved
+    avio_skip(pb, 16 - 2*nb_rates + 20); // empty entries of rate-map-table + reserved
 
     return 0;
 }
@@ -140,7 +148,7 @@ static int qcp_read_packet(AVFormatContext *s, AVPacket *pkt)
     QCPContext    *c  = s->priv_data;
     unsigned int  chunk_size, tag;
 
-    while(!url_feof(pb)) {
+    while(!avio_feof(pb)) {
         if (c->data_size) {
             int pkt_size, ret, mode = avio_r8(pb);
 
@@ -165,7 +173,7 @@ static int qcp_read_packet(AVFormatContext *s, AVPacket *pkt)
             return ret;
         }
 
-        if (url_ftell(pb) & 1 && avio_r8(pb))
+        if (avio_tell(pb) & 1 && avio_r8(pb))
             av_log(s, AV_LOG_WARNING, "Padding should be 0.\n");
 
         tag        = avio_rl32(pb);
@@ -174,14 +182,14 @@ static int qcp_read_packet(AVFormatContext *s, AVPacket *pkt)
         case MKTAG('v', 'r', 'a', 't'):
             if (avio_rl32(pb)) // var-rate-flag
                 s->packet_size = 0;
-            avio_seek(pb, 4, SEEK_CUR); // size-in-packets
+            avio_skip(pb, 4); // size-in-packets
             break;
         case MKTAG('d', 'a', 't', 'a'):
             c->data_size = chunk_size;
             break;
 
         default:
-            avio_seek(pb, chunk_size, SEEK_CUR);
+            avio_skip(pb, chunk_size);
         }
     }
     return AVERROR_EOF;
@@ -189,7 +197,7 @@ static int qcp_read_packet(AVFormatContext *s, AVPacket *pkt)
 
 AVInputFormat ff_qcp_demuxer = {
     .name           = "qcp",
-    .long_name      = NULL_IF_CONFIG_SMALL("QCP format"),
+    .long_name      = NULL_IF_CONFIG_SMALL("QCP"),
     .priv_data_size = sizeof(QCPContext),
     .read_probe     = qcp_probe,
     .read_header    = qcp_read_header,