Mercurial > libavcodec.hg
annotate libspeexdec.c @ 10381:9262948fd649 libavcodec
Hack: set the coded frame PTS to the incoming PTS.
This is not correct, but libtheora does not seem to provide a way
to get the correct value, and this is necessary to make encoding
produce sensible time stamps when encoded content is variable
FPS or the time base is simply different from FPS.
Somewhat fixes issue 1197.
author | reimar |
---|---|
date | Sat, 10 Oct 2009 14:43:31 +0000 |
parents | 691a0e5585a0 |
children | 8a4984c5cacc |
rev | line source |
---|---|
8047 | 1 /* |
2 * Copyright (C) 2008 David Conrad | |
3 * | |
4 * This file is part of FFmpeg. | |
5 * | |
6 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software | |
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 */ | |
20 | |
21 #include "avcodec.h" | |
22 #include <speex/speex.h> | |
23 #include <speex/speex_header.h> | |
24 #include <speex/speex_stereo.h> | |
25 #include <speex/speex_callbacks.h> | |
26 | |
27 typedef struct { | |
28 SpeexBits bits; | |
29 SpeexStereoState stereo; | |
30 void *dec_state; | |
31 SpeexHeader *header; | |
10116
6cade2cdd63b
Store the frame size in the LibSpeexContext in case the header does not exist.
jbr
parents:
10111
diff
changeset
|
32 int frame_size; |
8047 | 33 } LibSpeexContext; |
34 | |
35 | |
36 static av_cold int libspeex_decode_init(AVCodecContext *avctx) | |
37 { | |
38 LibSpeexContext *s = avctx->priv_data; | |
39 const SpeexMode *mode; | |
40 | |
41 // defaults in the case of a missing header | |
42 if (avctx->sample_rate <= 8000) | |
43 mode = &speex_nb_mode; | |
44 else if (avctx->sample_rate <= 16000) | |
45 mode = &speex_wb_mode; | |
46 else | |
47 mode = &speex_uwb_mode; | |
48 | |
49 if (avctx->extradata_size >= 80) | |
50 s->header = speex_packet_to_header(avctx->extradata, avctx->extradata_size); | |
51 | |
52 avctx->sample_fmt = SAMPLE_FMT_S16; | |
53 if (s->header) { | |
54 avctx->sample_rate = s->header->rate; | |
55 avctx->channels = s->header->nb_channels; | |
10116
6cade2cdd63b
Store the frame size in the LibSpeexContext in case the header does not exist.
jbr
parents:
10111
diff
changeset
|
56 avctx->frame_size = s->frame_size = s->header->frame_size; |
10110
4186efb86933
Modify the Ogg/Speex demuxer and the libspeex decoder so that they always treat
jbr
parents:
9355
diff
changeset
|
57 if (s->header->frames_per_packet) |
4186efb86933
Modify the Ogg/Speex demuxer and the libspeex decoder so that they always treat
jbr
parents:
9355
diff
changeset
|
58 avctx->frame_size *= s->header->frames_per_packet; |
8047 | 59 |
60 mode = speex_lib_get_mode(s->header->mode); | |
61 if (!mode) { | |
62 av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", s->header->mode); | |
63 return -1; | |
64 } | |
65 } else | |
8768
4bb782c7793e
cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents:
8047
diff
changeset
|
66 av_log(avctx, AV_LOG_INFO, "Missing Speex header, assuming defaults.\n"); |
8047 | 67 |
68 if (avctx->channels > 2) { | |
8768
4bb782c7793e
cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents:
8047
diff
changeset
|
69 av_log(avctx, AV_LOG_ERROR, "Only stereo and mono are supported.\n"); |
8047 | 70 return -1; |
71 } | |
72 | |
73 speex_bits_init(&s->bits); | |
74 s->dec_state = speex_decoder_init(mode); | |
75 if (!s->dec_state) { | |
8768
4bb782c7793e
cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents:
8047
diff
changeset
|
76 av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n"); |
8047 | 77 return -1; |
78 } | |
79 | |
10116
6cade2cdd63b
Store the frame size in the LibSpeexContext in case the header does not exist.
jbr
parents:
10111
diff
changeset
|
80 if (!s->header) { |
10124
691a0e5585a0
libspeex: Do not set AVCodecContext.frame_size in decoder init if there is no
jbr
parents:
10116
diff
changeset
|
81 speex_decoder_ctl(s->dec_state, SPEEX_GET_FRAME_SIZE, &s->frame_size); |
10116
6cade2cdd63b
Store the frame size in the LibSpeexContext in case the header does not exist.
jbr
parents:
10111
diff
changeset
|
82 } |
8047 | 83 |
84 if (avctx->channels == 2) { | |
85 SpeexCallback callback; | |
86 callback.callback_id = SPEEX_INBAND_STEREO; | |
87 callback.func = speex_std_stereo_request_handler; | |
88 callback.data = &s->stereo; | |
89 s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT; | |
90 speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback); | |
91 } | |
92 return 0; | |
93 } | |
94 | |
95 static int libspeex_decode_frame(AVCodecContext *avctx, | |
96 void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8768
diff
changeset
|
97 AVPacket *avpkt) |
8047 | 98 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8768
diff
changeset
|
99 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8768
diff
changeset
|
100 int buf_size = avpkt->size; |
8047 | 101 LibSpeexContext *s = avctx->priv_data; |
102 int16_t *output = data, *end; | |
103 int i, num_samples; | |
104 | |
10116
6cade2cdd63b
Store the frame size in the LibSpeexContext in case the header does not exist.
jbr
parents:
10111
diff
changeset
|
105 num_samples = s->frame_size * avctx->channels; |
10111
ebe5812b39a7
Use the output data type to determine the maximum number of samples that can be
jbr
parents:
10110
diff
changeset
|
106 end = output + *data_size / sizeof(*output); |
8047 | 107 |
108 speex_bits_read_from(&s->bits, buf, buf_size); | |
109 | |
110 for (i = 0; speex_bits_remaining(&s->bits) && output + num_samples < end; i++) { | |
111 int ret = speex_decode_int(s->dec_state, &s->bits, output); | |
112 if (ret <= -2) { | |
8768
4bb782c7793e
cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents:
8047
diff
changeset
|
113 av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n"); |
8047 | 114 return -1; |
115 } else if (ret == -1) | |
116 // end of stream | |
117 break; | |
118 | |
119 if (avctx->channels == 2) | |
10116
6cade2cdd63b
Store the frame size in the LibSpeexContext in case the header does not exist.
jbr
parents:
10111
diff
changeset
|
120 speex_decode_stereo_int(output, s->frame_size, &s->stereo); |
8047 | 121 |
122 output += num_samples; | |
123 } | |
124 | |
10116
6cade2cdd63b
Store the frame size in the LibSpeexContext in case the header does not exist.
jbr
parents:
10111
diff
changeset
|
125 avctx->frame_size = s->frame_size * i; |
10110
4186efb86933
Modify the Ogg/Speex demuxer and the libspeex decoder so that they always treat
jbr
parents:
9355
diff
changeset
|
126 *data_size = avctx->channels * avctx->frame_size * sizeof(*output); |
8047 | 127 return buf_size; |
128 } | |
129 | |
130 static av_cold int libspeex_decode_close(AVCodecContext *avctx) | |
131 { | |
132 LibSpeexContext *s = avctx->priv_data; | |
133 | |
134 speex_header_free(s->header); | |
135 speex_bits_destroy(&s->bits); | |
136 speex_decoder_destroy(s->dec_state); | |
137 | |
138 return 0; | |
139 } | |
140 | |
141 AVCodec libspeex_decoder = { | |
142 "libspeex", | |
143 CODEC_TYPE_AUDIO, | |
144 CODEC_ID_SPEEX, | |
145 sizeof(LibSpeexContext), | |
146 libspeex_decode_init, | |
147 NULL, | |
148 libspeex_decode_close, | |
149 libspeex_decode_frame, | |
8768
4bb782c7793e
cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents:
8047
diff
changeset
|
150 .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"), |
8047 | 151 }; |