annotate ffmpeg/libavcodec/libvorbisdec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Copyright (c) 2002 Mark Hills <mark@pogo.org.uk>
yading@10 3 *
yading@10 4 * This file is part of FFmpeg.
yading@10 5 *
yading@10 6 * FFmpeg is free software; you can redistribute it and/or
yading@10 7 * modify it under the terms of the GNU Lesser General Public
yading@10 8 * License as published by the Free Software Foundation; either
yading@10 9 * version 2.1 of the License, or (at your option) any later version.
yading@10 10 *
yading@10 11 * FFmpeg is distributed in the hope that it will be useful,
yading@10 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 14 * Lesser General Public License for more details.
yading@10 15 *
yading@10 16 * You should have received a copy of the GNU Lesser General Public
yading@10 17 * License along with FFmpeg; if not, write to the Free Software
yading@10 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 19 */
yading@10 20
yading@10 21 #include <vorbis/vorbisenc.h>
yading@10 22
yading@10 23 #include "avcodec.h"
yading@10 24 #include "bytestream.h"
yading@10 25 #include "internal.h"
yading@10 26
yading@10 27 typedef struct OggVorbisDecContext {
yading@10 28 vorbis_info vi; /**< vorbis_info used during init */
yading@10 29 vorbis_dsp_state vd; /**< DSP state used for analysis */
yading@10 30 vorbis_block vb; /**< vorbis_block used for analysis */
yading@10 31 vorbis_comment vc; /**< VorbisComment info */
yading@10 32 ogg_packet op; /**< ogg packet */
yading@10 33 } OggVorbisDecContext;
yading@10 34
yading@10 35 static int oggvorbis_decode_init(AVCodecContext *avccontext) {
yading@10 36 OggVorbisDecContext *context = avccontext->priv_data ;
yading@10 37 uint8_t *p= avccontext->extradata;
yading@10 38 int i, hsizes[3];
yading@10 39 unsigned char *headers[3], *extradata = avccontext->extradata;
yading@10 40
yading@10 41 vorbis_info_init(&context->vi) ;
yading@10 42 vorbis_comment_init(&context->vc) ;
yading@10 43
yading@10 44 if(! avccontext->extradata_size || ! p) {
yading@10 45 av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n");
yading@10 46 return -1;
yading@10 47 }
yading@10 48
yading@10 49 if(p[0] == 0 && p[1] == 30) {
yading@10 50 for(i = 0; i < 3; i++){
yading@10 51 hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
yading@10 52 headers[i] = p;
yading@10 53 p += hsizes[i];
yading@10 54 }
yading@10 55 } else if(*p == 2) {
yading@10 56 unsigned int offset = 1;
yading@10 57 p++;
yading@10 58 for(i=0; i<2; i++) {
yading@10 59 hsizes[i] = 0;
yading@10 60 while((*p == 0xFF) && (offset < avccontext->extradata_size)) {
yading@10 61 hsizes[i] += 0xFF;
yading@10 62 offset++;
yading@10 63 p++;
yading@10 64 }
yading@10 65 if(offset >= avccontext->extradata_size - 1) {
yading@10 66 av_log(avccontext, AV_LOG_ERROR,
yading@10 67 "vorbis header sizes damaged\n");
yading@10 68 return -1;
yading@10 69 }
yading@10 70 hsizes[i] += *p;
yading@10 71 offset++;
yading@10 72 p++;
yading@10 73 }
yading@10 74 hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset;
yading@10 75 #if 0
yading@10 76 av_log(avccontext, AV_LOG_DEBUG,
yading@10 77 "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
yading@10 78 hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size);
yading@10 79 #endif
yading@10 80 headers[0] = extradata + offset;
yading@10 81 headers[1] = extradata + offset + hsizes[0];
yading@10 82 headers[2] = extradata + offset + hsizes[0] + hsizes[1];
yading@10 83 } else {
yading@10 84 av_log(avccontext, AV_LOG_ERROR,
yading@10 85 "vorbis initial header len is wrong: %d\n", *p);
yading@10 86 return -1;
yading@10 87 }
yading@10 88
yading@10 89 for(i=0; i<3; i++){
yading@10 90 context->op.b_o_s= i==0;
yading@10 91 context->op.bytes = hsizes[i];
yading@10 92 context->op.packet = headers[i];
yading@10 93 if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
yading@10 94 av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
yading@10 95 return -1;
yading@10 96 }
yading@10 97 }
yading@10 98
yading@10 99 avccontext->channels = context->vi.channels;
yading@10 100 avccontext->sample_rate = context->vi.rate;
yading@10 101 avccontext->sample_fmt = AV_SAMPLE_FMT_S16;
yading@10 102 avccontext->time_base= (AVRational){1, avccontext->sample_rate};
yading@10 103
yading@10 104 vorbis_synthesis_init(&context->vd, &context->vi);
yading@10 105 vorbis_block_init(&context->vd, &context->vb);
yading@10 106
yading@10 107 return 0 ;
yading@10 108 }
yading@10 109
yading@10 110
yading@10 111 static inline int conv(int samples, float **pcm, char *buf, int channels) {
yading@10 112 int i, j;
yading@10 113 ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;
yading@10 114 float *mono ;
yading@10 115
yading@10 116 for(i = 0 ; i < channels ; i++){
yading@10 117 ptr = &data[i];
yading@10 118 mono = pcm[i] ;
yading@10 119
yading@10 120 for(j = 0 ; j < samples ; j++) {
yading@10 121 *ptr = av_clip_int16(mono[j] * 32767.f);
yading@10 122 ptr += channels;
yading@10 123 }
yading@10 124 }
yading@10 125
yading@10 126 return 0 ;
yading@10 127 }
yading@10 128
yading@10 129 static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
yading@10 130 int *got_frame_ptr, AVPacket *avpkt)
yading@10 131 {
yading@10 132 OggVorbisDecContext *context = avccontext->priv_data ;
yading@10 133 AVFrame *frame = data;
yading@10 134 float **pcm ;
yading@10 135 ogg_packet *op= &context->op;
yading@10 136 int samples, total_samples, total_bytes;
yading@10 137 int ret;
yading@10 138 int16_t *output;
yading@10 139
yading@10 140 if(!avpkt->size){
yading@10 141 //FIXME flush
yading@10 142 return 0;
yading@10 143 }
yading@10 144
yading@10 145 frame->nb_samples = 8192*4;
yading@10 146 if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0)
yading@10 147 return ret;
yading@10 148 output = (int16_t *)frame->data[0];
yading@10 149
yading@10 150
yading@10 151 op->packet = avpkt->data;
yading@10 152 op->bytes = avpkt->size;
yading@10 153
yading@10 154 // 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);
yading@10 155
yading@10 156 /* for(i=0; i<op->bytes; i++)
yading@10 157 av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
yading@10 158 av_log(avccontext, AV_LOG_DEBUG, "\n");*/
yading@10 159
yading@10 160 if(vorbis_synthesis(&context->vb, op) == 0)
yading@10 161 vorbis_synthesis_blockin(&context->vd, &context->vb) ;
yading@10 162
yading@10 163 total_samples = 0 ;
yading@10 164 total_bytes = 0 ;
yading@10 165
yading@10 166 while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) {
yading@10 167 conv(samples, pcm, (char*)output + total_bytes, context->vi.channels) ;
yading@10 168 total_bytes += samples * 2 * context->vi.channels ;
yading@10 169 total_samples += samples ;
yading@10 170 vorbis_synthesis_read(&context->vd, samples) ;
yading@10 171 }
yading@10 172
yading@10 173 frame->nb_samples = total_samples;
yading@10 174 *got_frame_ptr = 1;
yading@10 175 return avpkt->size;
yading@10 176 }
yading@10 177
yading@10 178
yading@10 179 static int oggvorbis_decode_close(AVCodecContext *avccontext) {
yading@10 180 OggVorbisDecContext *context = avccontext->priv_data ;
yading@10 181
yading@10 182 vorbis_info_clear(&context->vi) ;
yading@10 183 vorbis_comment_clear(&context->vc) ;
yading@10 184
yading@10 185 return 0 ;
yading@10 186 }
yading@10 187
yading@10 188
yading@10 189 AVCodec ff_libvorbis_decoder = {
yading@10 190 .name = "libvorbis",
yading@10 191 .type = AVMEDIA_TYPE_AUDIO,
yading@10 192 .id = AV_CODEC_ID_VORBIS,
yading@10 193 .priv_data_size = sizeof(OggVorbisDecContext),
yading@10 194 .init = oggvorbis_decode_init,
yading@10 195 .decode = oggvorbis_decode_frame,
yading@10 196 .close = oggvorbis_decode_close,
yading@10 197 .capabilities = CODEC_CAP_DELAY,
yading@10 198 .long_name = NULL_IF_CONFIG_SMALL("libvorbis"),
yading@10 199 };