FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
libvorbisdec.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002 Mark Hills <mark@pogo.org.uk>
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 <vorbis/vorbisenc.h>
22 
23 #include "avcodec.h"
24 #include "bytestream.h"
25 #include "internal.h"
26 
27 typedef struct OggVorbisDecContext {
28  vorbis_info vi; /**< vorbis_info used during init */
29  vorbis_dsp_state vd; /**< DSP state used for analysis */
30  vorbis_block vb; /**< vorbis_block used for analysis */
31  vorbis_comment vc; /**< VorbisComment info */
32  ogg_packet op; /**< ogg packet */
34 
35 static int oggvorbis_decode_close(AVCodecContext *avccontext);
36 
37 static int oggvorbis_decode_init(AVCodecContext *avccontext) {
38  OggVorbisDecContext *context = avccontext->priv_data ;
39  uint8_t *p= avccontext->extradata;
40  int i, hsizes[3], ret;
41  unsigned char *headers[3], *extradata = avccontext->extradata;
42 
43  if(! avccontext->extradata_size || ! p) {
44  av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n");
45  return AVERROR(EINVAL);
46  }
47 
48  vorbis_info_init(&context->vi) ;
49  vorbis_comment_init(&context->vc) ;
50 
51  if(p[0] == 0 && p[1] == 30) {
52  for(i = 0; i < 3; i++){
53  hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
54  headers[i] = p;
55  p += hsizes[i];
56  }
57  } else if(*p == 2) {
58  unsigned int offset = 1;
59  p++;
60  for(i=0; i<2; i++) {
61  hsizes[i] = 0;
62  while((*p == 0xFF) && (offset < avccontext->extradata_size)) {
63  hsizes[i] += 0xFF;
64  offset++;
65  p++;
66  }
67  if(offset >= avccontext->extradata_size - 1) {
68  av_log(avccontext, AV_LOG_ERROR,
69  "vorbis header sizes damaged\n");
70  ret = AVERROR_INVALIDDATA;
71  goto error;
72  }
73  hsizes[i] += *p;
74  offset++;
75  p++;
76  }
77  hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset;
78 #if 0
79  av_log(avccontext, AV_LOG_DEBUG,
80  "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
81  hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size);
82 #endif
83  headers[0] = extradata + offset;
84  headers[1] = extradata + offset + hsizes[0];
85  headers[2] = extradata + offset + hsizes[0] + hsizes[1];
86  } else {
87  av_log(avccontext, AV_LOG_ERROR,
88  "vorbis initial header len is wrong: %d\n", *p);
89  ret = AVERROR_INVALIDDATA;
90  goto error;
91  }
92 
93  for(i=0; i<3; i++){
94  context->op.b_o_s= i==0;
95  context->op.bytes = hsizes[i];
96  context->op.packet = headers[i];
97  if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
98  av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
99  ret = AVERROR_INVALIDDATA;
100  goto error;
101  }
102  }
103 
104  avccontext->channels = context->vi.channels;
105  avccontext->sample_rate = context->vi.rate;
106  avccontext->sample_fmt = AV_SAMPLE_FMT_S16;
107  avccontext->time_base= (AVRational){1, avccontext->sample_rate};
108 
109  vorbis_synthesis_init(&context->vd, &context->vi);
110  vorbis_block_init(&context->vd, &context->vb);
111 
112  return 0 ;
113 
114  error:
115  oggvorbis_decode_close(avccontext);
116  return ret;
117 }
118 
119 
120 static inline int conv(int samples, float **pcm, char *buf, int channels) {
121  int i, j;
122  ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;
123  float *mono ;
124 
125  for(i = 0 ; i < channels ; i++){
126  ptr = &data[i];
127  mono = pcm[i] ;
128 
129  for(j = 0 ; j < samples ; j++) {
130  *ptr = av_clip_int16(mono[j] * 32767.f);
131  ptr += channels;
132  }
133  }
134 
135  return 0 ;
136 }
137 
138 static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
139  int *got_frame_ptr, AVPacket *avpkt)
140 {
141  OggVorbisDecContext *context = avccontext->priv_data ;
142  AVFrame *frame = data;
143  float **pcm ;
144  ogg_packet *op= &context->op;
145  int samples, total_samples, total_bytes;
146  int ret;
147  int16_t *output;
148 
149  if(!avpkt->size){
150  //FIXME flush
151  return 0;
152  }
153 
154  frame->nb_samples = 8192*4;
155  if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0)
156  return ret;
157  output = (int16_t *)frame->data[0];
158 
159 
160  op->packet = avpkt->data;
161  op->bytes = avpkt->size;
162 
163 // av_log(avccontext, AV_LOG_DEBUG, "%d %d %d %"PRId64" %"PRId64" %d %d\n", op->bytes, op->b_o_s, op->e_o_s, op->granulepos, op->packetno, buf_size, context->vi.rate);
164 
165 /* for(i=0; i<op->bytes; i++)
166  av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
167  av_log(avccontext, AV_LOG_DEBUG, "\n");*/
168 
169  if(vorbis_synthesis(&context->vb, op) == 0)
170  vorbis_synthesis_blockin(&context->vd, &context->vb) ;
171 
172  total_samples = 0 ;
173  total_bytes = 0 ;
174 
175  while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) {
176  conv(samples, pcm, (char*)output + total_bytes, context->vi.channels) ;
177  total_bytes += samples * 2 * context->vi.channels ;
178  total_samples += samples ;
179  vorbis_synthesis_read(&context->vd, samples) ;
180  }
181 
182  frame->nb_samples = total_samples;
183  *got_frame_ptr = total_samples > 0;
184  return avpkt->size;
185 }
186 
187 
188 static int oggvorbis_decode_close(AVCodecContext *avccontext) {
189  OggVorbisDecContext *context = avccontext->priv_data ;
190 
191  vorbis_block_clear(&context->vb);
192  vorbis_dsp_clear(&context->vd);
193  vorbis_info_clear(&context->vi) ;
194  vorbis_comment_clear(&context->vc) ;
195 
196  return 0 ;
197 }
198 
199 
201  .name = "libvorbis",
202  .long_name = NULL_IF_CONFIG_SMALL("libvorbis"),
203  .type = AVMEDIA_TYPE_AUDIO,
204  .id = AV_CODEC_ID_VORBIS,
205  .priv_data_size = sizeof(OggVorbisDecContext),
208  .close = oggvorbis_decode_close,
209  .capabilities = AV_CODEC_CAP_DELAY,
210 };
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:187
ogg_packet op
ogg packet
Definition: libvorbisdec.c:32
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static int conv(int samples, float **pcm, char *buf, int channels)
Definition: libvorbisdec.c:120
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
vorbis_dsp_state vd
DSP state used for analysis.
Definition: libvorbisdec.c:29
int size
Definition: avcodec.h:1658
AVCodec.
Definition: avcodec.h:3681
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1869
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition: avcodec.h:1019
vorbis_block vb
vorbis_block used for analysis
Definition: libvorbisdec.c:30
enum AVSampleFormat sample_fmt
audio sample format
Definition: avcodec.h:2502
uint8_t
static int oggvorbis_decode_init(AVCodecContext *avccontext)
Definition: libvorbisdec.c:37
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1847
static AVFrame * frame
uint8_t * data
Definition: avcodec.h:1657
#define av_log(a,...)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
vorbis_comment vc
VorbisComment info.
Definition: libvorbisdec.c:31
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:179
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
const char * name
Name of the codec implementation.
Definition: avcodec.h:3688
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
vorbis_info vi
vorbis_info used during init
Definition: libvorbisdec.c:28
static void error(const char *err)
Libavcodec external API header.
static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data, int *got_frame_ptr, AVPacket *avpkt)
Definition: libvorbisdec.c:138
int sample_rate
samples per second
Definition: avcodec.h:2494
static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, int64_t *fpos)
find the next Ogg packet
Definition: oggdec.c:474
main external API structure.
Definition: avcodec.h:1732
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: utils.c:953
static int oggvorbis_decode_close(AVCodecContext *avccontext)
Definition: libvorbisdec.c:188
void * buf
Definition: avisynth_c.h:690
int extradata_size
Definition: avcodec.h:1848
Rational number (pair of numerator and denominator).
Definition: rational.h:58
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:201
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition: anm.c:78
common internal api header.
signed 16 bits
Definition: samplefmt.h:61
AVCodec ff_libvorbis_decoder
Definition: libvorbisdec.c:200
void * priv_data
Definition: avcodec.h:1774
int channels
number of audio channels
Definition: avcodec.h:2495
static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt)
Definition: ffmpeg.c:2257
This structure stores compressed data.
Definition: avcodec.h:1634
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:244