• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/qcp.c

Go to the documentation of this file.
00001 /*
00002  * QCP format (.qcp) demuxer
00003  * Copyright (c) 2009 Kenan Gillet
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00030 #include "libavutil/intreadwrite.h"
00031 #include "avformat.h"
00032 
00033 typedef struct {
00034     uint32_t data_size;                     
00035 
00036 #define QCP_MAX_MODE 4
00037     int16_t rates_per_mode[QCP_MAX_MODE+1]; 
00038 
00039 } QCPContext;
00040 
00045 static const uint8_t guid_qcelp_13k_part[15] = {
00046     0x6d, 0x7f, 0x5e, 0x15, 0xb1, 0xd0, 0x11, 0xba,
00047     0x91, 0x00, 0x80, 0x5f, 0xb4, 0xb9, 0x7e
00048 };
00049 
00053 static const uint8_t guid_evrc[16] = {
00054     0x8d, 0xd4, 0x89, 0xe6, 0x76, 0x90, 0xb5, 0x46,
00055     0x91, 0xef, 0x73, 0x6a, 0x51, 0x00, 0xce, 0xb4
00056 };
00057 
00061 static const uint8_t guid_smv[16] = {
00062     0x75, 0x2b, 0x7c, 0x8d, 0x97, 0xa7, 0x49, 0xed,
00063     0x98, 0x5e, 0xd5, 0x3c, 0x8c, 0xc7, 0x5f, 0x84
00064 };
00065 
00070 static int is_qcelp_13k_guid(const uint8_t *guid) {
00071     return (guid[0] == 0x41 || guid[0] == 0x42)
00072         && !memcmp(guid+1, guid_qcelp_13k_part, sizeof(guid_qcelp_13k_part));
00073 }
00074 
00075 static int qcp_probe(AVProbeData *pd)
00076 {
00077     if (AV_RL32(pd->buf  ) == AV_RL32("RIFF") &&
00078         AV_RL64(pd->buf+8) == AV_RL64("QLCMfmt "))
00079         return AVPROBE_SCORE_MAX;
00080     return 0;
00081 }
00082 
00083 static int qcp_read_header(AVFormatContext *s, AVFormatParameters *ap)
00084 {
00085     ByteIOContext *pb = s->pb;
00086     QCPContext    *c  = s->priv_data;
00087     AVStream      *st = av_new_stream(s, 0);
00088     uint8_t       buf[16];
00089     int           i, nb_rates;
00090 
00091     if (!st)
00092         return AVERROR(ENOMEM);
00093 
00094     get_be32(pb);                    // "RIFF"
00095     s->file_size = get_le32(pb) + 8;
00096     url_fskip(pb, 8 + 4 + 1 + 1);    // "QLCMfmt " + chunk-size + major-version + minor-version
00097 
00098     st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00099     st->codec->channels   = 1;
00100     get_buffer(pb, buf, 16);
00101     if (is_qcelp_13k_guid(buf)) {
00102         st->codec->codec_id = CODEC_ID_QCELP;
00103     } else if (!memcmp(buf, guid_evrc, 16)) {
00104         av_log(s, AV_LOG_ERROR, "EVRC codec is not supported.\n");
00105         return AVERROR_PATCHWELCOME;
00106     } else if (!memcmp(buf, guid_smv, 16)) {
00107         av_log(s, AV_LOG_ERROR, "SMV codec is not supported.\n");
00108         return AVERROR_PATCHWELCOME;
00109     } else {
00110         av_log(s, AV_LOG_ERROR, "Unknown codec GUID.\n");
00111         return AVERROR_INVALIDDATA;
00112     }
00113     url_fskip(pb, 2 + 80); // codec-version + codec-name
00114     st->codec->bit_rate = get_le16(pb);
00115 
00116     s->packet_size = get_le16(pb);
00117     url_fskip(pb, 2); // block-size
00118     st->codec->sample_rate = get_le16(pb);
00119     url_fskip(pb, 2); // sample-size
00120 
00121     memset(c->rates_per_mode, -1, sizeof(c->rates_per_mode));
00122     nb_rates = get_le32(pb);
00123     nb_rates = FFMIN(nb_rates, 8);
00124     for (i=0; i<nb_rates; i++) {
00125         int size = get_byte(pb);
00126         int mode = get_byte(pb);
00127         if (mode > QCP_MAX_MODE) {
00128             av_log(s, AV_LOG_WARNING, "Unknown entry %d=>%d in rate-map-table.\n ", mode, size);
00129         } else
00130             c->rates_per_mode[mode] = size;
00131     }
00132     url_fskip(pb, 16 - 2*nb_rates + 20); // empty entries of rate-map-table + reserved
00133 
00134     return 0;
00135 }
00136 
00137 static int qcp_read_packet(AVFormatContext *s, AVPacket *pkt)
00138 {
00139     ByteIOContext *pb = s->pb;
00140     QCPContext    *c  = s->priv_data;
00141     unsigned int  chunk_size, tag;
00142 
00143     while(!url_feof(pb)) {
00144         if (c->data_size) {
00145             int pkt_size, ret, mode = get_byte(pb);
00146 
00147             if (s->packet_size) {
00148                 pkt_size = s->packet_size - 1;
00149             } else if (mode > QCP_MAX_MODE || (pkt_size = c->rates_per_mode[mode]) < 0) {
00150                 c->data_size--;
00151                 continue;
00152             }
00153 
00154             if (c->data_size <= pkt_size) {
00155                 av_log(s, AV_LOG_WARNING, "Data chunk is too small.\n");
00156                 pkt_size = c->data_size - 1;
00157             }
00158 
00159             if ((ret = av_get_packet(pb, pkt, pkt_size)) >= 0) {
00160                 if (pkt_size != ret)
00161                     av_log(s, AV_LOG_ERROR, "Packet size is too small.\n");
00162 
00163                 c->data_size -= pkt_size + 1;
00164             }
00165             return ret;
00166         }
00167 
00168         if (url_ftell(pb) & 1 && get_byte(pb))
00169             av_log(s, AV_LOG_WARNING, "Padding should be 0.\n");
00170 
00171         tag        = get_le32(pb);
00172         chunk_size = get_le32(pb);
00173         switch (tag) {
00174         case MKTAG('v', 'r', 'a', 't'):
00175             if (get_le32(pb)) // var-rate-flag
00176                 s->packet_size = 0;
00177             url_fskip(pb, 4); // size-in-packets
00178             break;
00179         case MKTAG('d', 'a', 't', 'a'):
00180             c->data_size = chunk_size;
00181             break;
00182 
00183         default:
00184             url_fskip(pb, chunk_size);
00185         }
00186     }
00187     return AVERROR_EOF;
00188 }
00189 
00190 AVInputFormat qcp_demuxer = {
00191     .name           = "qcp",
00192     .long_name      = NULL_IF_CONFIG_SMALL("QCP format"),
00193     .priv_data_size = sizeof(QCPContext),
00194     .read_probe     = qcp_probe,
00195     .read_header    = qcp_read_header,
00196     .read_packet    = qcp_read_packet,
00197 };

Generated on Fri Sep 16 2011 17:17:50 for FFmpeg by  doxygen 1.7.1