Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * RAW GSM demuxer
  3.  * Copyright (c) 2011 Justin Ruggles
  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/channel_layout.h"
  23. #include "libavutil/mathematics.h"
  24. #include "libavutil/opt.h"
  25. #include "avformat.h"
  26. #include "internal.h"
  27.  
  28. #define GSM_BLOCK_SIZE    33
  29. #define GSM_BLOCK_SAMPLES 160
  30. #define GSM_SAMPLE_RATE   8000
  31.  
  32. typedef struct {
  33.     AVClass *class;
  34.     int sample_rate;
  35. } GSMDemuxerContext;
  36.  
  37. static int gsm_read_packet(AVFormatContext *s, AVPacket *pkt)
  38. {
  39.     int ret, size;
  40.  
  41.     size = GSM_BLOCK_SIZE;
  42.  
  43.     pkt->pos = avio_tell(s->pb);
  44.     pkt->stream_index = 0;
  45.  
  46.     ret = av_get_packet(s->pb, pkt, size);
  47.     if (ret < GSM_BLOCK_SIZE) {
  48.         av_free_packet(pkt);
  49.         return ret < 0 ? ret : AVERROR(EIO);
  50.     }
  51.     pkt->duration = 1;
  52.     pkt->pts      = pkt->pos / GSM_BLOCK_SIZE;
  53.  
  54.     return 0;
  55. }
  56.  
  57. static int gsm_read_header(AVFormatContext *s)
  58. {
  59.     GSMDemuxerContext *c = s->priv_data;
  60.     AVStream *st = avformat_new_stream(s, NULL);
  61.     if (!st)
  62.         return AVERROR(ENOMEM);
  63.  
  64.     st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
  65.     st->codec->codec_id    = s->iformat->raw_codec_id;
  66.     st->codec->channels    = 1;
  67.     st->codec->channel_layout = AV_CH_LAYOUT_MONO;
  68.     st->codec->sample_rate = c->sample_rate;
  69.     st->codec->bit_rate    = GSM_BLOCK_SIZE * 8 * c->sample_rate / GSM_BLOCK_SAMPLES;
  70.  
  71.     avpriv_set_pts_info(st, 64, GSM_BLOCK_SAMPLES, GSM_SAMPLE_RATE);
  72.  
  73.     return 0;
  74. }
  75.  
  76. static const AVOption options[] = {
  77.     { "sample_rate", "", offsetof(GSMDemuxerContext, sample_rate),
  78.        AV_OPT_TYPE_INT, {.i64 = GSM_SAMPLE_RATE}, 1, INT_MAX / GSM_BLOCK_SIZE,
  79.        AV_OPT_FLAG_DECODING_PARAM },
  80.     { NULL },
  81. };
  82.  
  83. static const AVClass gsm_class = {
  84.     .class_name = "gsm demuxer",
  85.     .item_name  = av_default_item_name,
  86.     .option     = options,
  87.     .version    = LIBAVUTIL_VERSION_INT,
  88. };
  89.  
  90. AVInputFormat ff_gsm_demuxer = {
  91.     .name           = "gsm",
  92.     .long_name      = NULL_IF_CONFIG_SMALL("raw GSM"),
  93.     .priv_data_size = sizeof(GSMDemuxerContext),
  94.     .read_header    = gsm_read_header,
  95.     .read_packet    = gsm_read_packet,
  96.     .flags          = AVFMT_GENERIC_INDEX,
  97.     .extensions     = "gsm",
  98.     .raw_codec_id   = AV_CODEC_ID_GSM,
  99.     .priv_class     = &gsm_class,
  100. };
  101.