Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * NIST Sphere demuxer
  3.  * Copyright (c) 2012 Paul B Mahol
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include "libavutil/avstring.h"
  23. #include "libavutil/intreadwrite.h"
  24. #include "avformat.h"
  25. #include "internal.h"
  26. #include "pcm.h"
  27.  
  28. static int nist_probe(AVProbeData *p)
  29. {
  30.     if (AV_RL64(p->buf) == AV_RL64("NIST_1A\x0a"))
  31.         return AVPROBE_SCORE_MAX;
  32.     return 0;
  33. }
  34.  
  35. static int nist_read_header(AVFormatContext *s)
  36. {
  37.     char buffer[32], coding[32] = "pcm", format[32] = "01";
  38.     int bps = 0, be = 0;
  39.     int32_t header_size;
  40.     AVStream *st;
  41.  
  42.     st = avformat_new_stream(s, NULL);
  43.     if (!st)
  44.         return AVERROR(ENOMEM);
  45.  
  46.     st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
  47.  
  48.     ff_get_line(s->pb, buffer, sizeof(buffer));
  49.     ff_get_line(s->pb, buffer, sizeof(buffer));
  50.     sscanf(buffer, "%"SCNd32, &header_size);
  51.     if (header_size <= 0)
  52.         return AVERROR_INVALIDDATA;
  53.  
  54.     while (!url_feof(s->pb)) {
  55.         ff_get_line(s->pb, buffer, sizeof(buffer));
  56.  
  57.         if (avio_tell(s->pb) >= header_size)
  58.             return AVERROR_INVALIDDATA;
  59.  
  60.         if (!memcmp(buffer, "end_head", 8)) {
  61.             if (!st->codec->bits_per_coded_sample)
  62.                 st->codec->bits_per_coded_sample = bps << 3;
  63.  
  64.             if (!av_strcasecmp(coding, "pcm")) {
  65.                 st->codec->codec_id = ff_get_pcm_codec_id(st->codec->bits_per_coded_sample,
  66.                                                           0, be, 0xFFFF);
  67.             } else if (!av_strcasecmp(coding, "alaw")) {
  68.                 st->codec->codec_id = AV_CODEC_ID_PCM_ALAW;
  69.             } else if (!av_strcasecmp(coding, "ulaw") ||
  70.                        !av_strcasecmp(coding, "mu-law")) {
  71.                 st->codec->codec_id = AV_CODEC_ID_PCM_MULAW;
  72.             } else {
  73.                 avpriv_request_sample(s, "coding %s", coding);
  74.             }
  75.  
  76.             avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
  77.  
  78.             st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8;
  79.  
  80.             if (avio_tell(s->pb) > header_size)
  81.                 return AVERROR_INVALIDDATA;
  82.  
  83.             avio_skip(s->pb, header_size - avio_tell(s->pb));
  84.  
  85.             return 0;
  86.         } else if (!memcmp(buffer, "channel_count", 13)) {
  87.             sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->channels);
  88.         } else if (!memcmp(buffer, "sample_byte_format", 18)) {
  89.             sscanf(buffer, "%*s %*s %31s", format);
  90.  
  91.             if (!av_strcasecmp(format, "01")) {
  92.                 be = 0;
  93.             } else if (!av_strcasecmp(format, "10")) {
  94.                 be = 1;
  95.             } else if (av_strcasecmp(format, "1")) {
  96.                 avpriv_request_sample(s, "sample byte format %s", format);
  97.                 return AVERROR_PATCHWELCOME;
  98.             }
  99.         } else if (!memcmp(buffer, "sample_coding", 13)) {
  100.             sscanf(buffer, "%*s %*s %31s", coding);
  101.         } else if (!memcmp(buffer, "sample_count", 12)) {
  102.             sscanf(buffer, "%*s %*s %"SCNd64, &st->duration);
  103.         } else if (!memcmp(buffer, "sample_n_bytes", 14)) {
  104.             sscanf(buffer, "%*s %*s %"SCNd32, &bps);
  105.         } else if (!memcmp(buffer, "sample_rate", 11)) {
  106.             sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->sample_rate);
  107.         } else if (!memcmp(buffer, "sample_sig_bits", 15)) {
  108.             sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->bits_per_coded_sample);
  109.         } else {
  110.             char key[32], value[32];
  111.             sscanf(buffer, "%31s %*s %31s", key, value);
  112.             av_dict_set(&s->metadata, key, value, AV_DICT_APPEND);
  113.         }
  114.     }
  115.  
  116.     return AVERROR_EOF;
  117. }
  118.  
  119. AVInputFormat ff_nistsphere_demuxer = {
  120.     .name           = "nistsphere",
  121.     .long_name      = NULL_IF_CONFIG_SMALL("NIST SPeech HEader REsources"),
  122.     .read_probe     = nist_probe,
  123.     .read_header    = nist_read_header,
  124.     .read_packet    = ff_pcm_read_packet,
  125.     .read_seek      = ff_pcm_read_seek,
  126.     .extensions     = "nist,sph",
  127.     .flags          = AVFMT_GENERIC_INDEX,
  128. };
  129.