Browse code

Create separate functions for the raw GSM demuxer.

Put the new raw GSM demuxer in its own file.
Fixes raw GSM demuxing.

Justin Ruggles authored on 2011/10/28 13:07:32
Showing 3 changed files
... ...
@@ -85,7 +85,7 @@ OBJS-$(CONFIG_FOURXM_DEMUXER)            += 4xm.o
85 85
 OBJS-$(CONFIG_FRAMECRC_MUXER)            += framecrcenc.o
86 86
 OBJS-$(CONFIG_FRAMEMD5_MUXER)            += md5enc.o
87 87
 OBJS-$(CONFIG_GIF_MUXER)                 += gif.o
88
-OBJS-$(CONFIG_GSM_DEMUXER)               += rawdec.o
88
+OBJS-$(CONFIG_GSM_DEMUXER)               += gsmdec.o
89 89
 OBJS-$(CONFIG_GXF_DEMUXER)               += gxf.o
90 90
 OBJS-$(CONFIG_GXF_MUXER)                 += gxfenc.o audiointerleave.o
91 91
 OBJS-$(CONFIG_G722_DEMUXER)              += rawdec.o
92 92
new file mode 100644
... ...
@@ -0,0 +1,135 @@
0
+/*
1
+ * RAW GSM demuxer
2
+ * Copyright (c) 2011 Justin Ruggles
3
+ *
4
+ * This file is part of Libav.
5
+ *
6
+ * Libav is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * Libav is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with Libav; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include "libavutil/mathematics.h"
22
+#include "libavutil/opt.h"
23
+#include "avformat.h"
24
+
25
+#define GSM_BLOCK_SIZE    33
26
+#define GSM_BLOCK_SAMPLES 160
27
+#define GSM_SAMPLE_RATE   8000
28
+
29
+typedef struct {
30
+    AVClass *class;
31
+    int sample_rate;
32
+} GSMDemuxerContext;
33
+
34
+static int gsm_read_packet(AVFormatContext *s, AVPacket *pkt)
35
+{
36
+    int ret, size;
37
+
38
+    size = GSM_BLOCK_SIZE * 32;
39
+
40
+    if (av_new_packet(pkt, size) < 0)
41
+        return AVERROR(ENOMEM);
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->size     = ret;
52
+    pkt->duration = ret      / GSM_BLOCK_SIZE;
53
+    pkt->pts      = pkt->pos / GSM_BLOCK_SIZE;
54
+
55
+    return 0;
56
+}
57
+
58
+static int gsm_read_header(AVFormatContext *s, AVFormatParameters *ap)
59
+{
60
+    GSMDemuxerContext *c = s->priv_data;
61
+    AVStream *st = avformat_new_stream(s, NULL);
62
+    if (!st)
63
+        return AVERROR(ENOMEM);
64
+
65
+    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
66
+    st->codec->codec_id    = s->iformat->value;
67
+    st->codec->channels    = 1;
68
+    st->codec->sample_rate = c->sample_rate;
69
+    st->codec->block_align = GSM_BLOCK_SIZE;
70
+    st->codec->bit_rate    = GSM_BLOCK_SIZE * 8 * c->sample_rate / GSM_BLOCK_SAMPLES;
71
+
72
+    av_set_pts_info(st, 64, GSM_BLOCK_SAMPLES, GSM_SAMPLE_RATE);
73
+
74
+    return 0;
75
+}
76
+
77
+static int gsm_read_seek2(AVFormatContext *s, int stream_index, int64_t min_ts,
78
+                          int64_t ts, int64_t max_ts, int flags)
79
+{
80
+    GSMDemuxerContext *c = s->priv_data;
81
+
82
+    /* convert timestamps to file positions */
83
+    if (!(flags & AVSEEK_FLAG_BYTE)) {
84
+        if (stream_index < 0) {
85
+            AVRational bitrate_q = { GSM_BLOCK_SAMPLES, c->sample_rate * GSM_BLOCK_SIZE };
86
+            ts     = av_rescale_q(ts,     AV_TIME_BASE_Q, bitrate_q);
87
+            min_ts = av_rescale_q(min_ts, AV_TIME_BASE_Q, bitrate_q);
88
+            max_ts = av_rescale_q(max_ts, AV_TIME_BASE_Q, bitrate_q);
89
+        } else {
90
+            ts     *= GSM_BLOCK_SIZE;
91
+            min_ts *= GSM_BLOCK_SIZE;
92
+            max_ts *= GSM_BLOCK_SIZE;
93
+        }
94
+    }
95
+    /* round to nearest block boundary */
96
+    ts = (ts + GSM_BLOCK_SIZE / 2) / GSM_BLOCK_SIZE * GSM_BLOCK_SIZE;
97
+    ts = FFMAX(0, ts);
98
+
99
+    /* handle min/max */
100
+    while (ts < min_ts)
101
+        ts += GSM_BLOCK_SIZE;
102
+    while (ts > max_ts)
103
+        ts -= GSM_BLOCK_SIZE;
104
+    if (ts < min_ts || ts > max_ts)
105
+        return -1;
106
+
107
+    return avio_seek(s->pb, ts, SEEK_SET);
108
+}
109
+
110
+static const AVOption options[] = {
111
+    { "sample_rate", "", offsetof(GSMDemuxerContext, sample_rate),
112
+       AV_OPT_TYPE_INT, {.dbl = GSM_SAMPLE_RATE}, 1, INT_MAX / GSM_BLOCK_SIZE,
113
+       AV_OPT_FLAG_DECODING_PARAM },
114
+    { NULL },
115
+};
116
+
117
+static const AVClass class = {
118
+    .class_name = "gsm demuxer",
119
+    .item_name  = av_default_item_name,
120
+    .option     = options,
121
+    .version    = LIBAVUTIL_VERSION_INT,
122
+};
123
+
124
+AVInputFormat ff_gsm_demuxer = {
125
+    .name           = "gsm",
126
+    .long_name      = NULL_IF_CONFIG_SMALL("raw GSM"),
127
+    .priv_data_size = sizeof(GSMDemuxerContext),
128
+    .read_header    = gsm_read_header,
129
+    .read_packet    = gsm_read_packet,
130
+    .read_seek2     = gsm_read_seek2,
131
+    .extensions     = "gsm",
132
+    .value          = CODEC_ID_GSM,
133
+    .priv_class     = &class,
134
+};
... ...
@@ -186,18 +186,6 @@ AVInputFormat ff_g722_demuxer = {
186 186
 };
187 187
 #endif
188 188
 
189
-#if CONFIG_GSM_DEMUXER
190
-AVInputFormat ff_gsm_demuxer = {
191
-    .name           = "gsm",
192
-    .long_name      = NULL_IF_CONFIG_SMALL("raw GSM"),
193
-    .read_header    = ff_raw_audio_read_header,
194
-    .read_packet    = ff_raw_read_partial_packet,
195
-    .flags= AVFMT_GENERIC_INDEX,
196
-    .extensions = "gsm",
197
-    .value = CODEC_ID_GSM,
198
-};
199
-#endif
200
-
201 189
 #if CONFIG_LATM_DEMUXER
202 190
 AVInputFormat ff_latm_demuxer = {
203 191
     .name           = "latm",