tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

libvorbisdec.c (7433B)


      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 "codec_internal.h"
     26 #include "decode.h"
     27 
     28 typedef struct OggVorbisDecContext {
     29    vorbis_info vi;                     /**< vorbis_info used during init   */
     30    vorbis_dsp_state vd;                /**< DSP state used for analysis    */
     31    vorbis_block vb;                    /**< vorbis_block used for analysis */
     32    vorbis_comment vc;                  /**< VorbisComment info             */
     33    ogg_packet op;                      /**< ogg packet                     */
     34 } OggVorbisDecContext;
     35 
     36 static int oggvorbis_decode_close(AVCodecContext *avccontext);
     37 
     38 static int oggvorbis_decode_init(AVCodecContext *avccontext) {
     39    OggVorbisDecContext *context = avccontext->priv_data ;
     40    uint8_t *p= avccontext->extradata;
     41    int i, hsizes[3], ret;
     42    unsigned char *headers[3], *extradata = avccontext->extradata;
     43 
     44    if(! avccontext->extradata_size || ! p) {
     45        av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n");
     46        return AVERROR(EINVAL);
     47    }
     48 
     49    vorbis_info_init(&context->vi) ;
     50    vorbis_comment_init(&context->vc) ;
     51 
     52    if(p[0] == 0 && p[1] == 30) {
     53        int sizesum = 0;
     54        for(i = 0; i < 3; i++){
     55            hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
     56            sizesum += 2 + hsizes[i];
     57            if (sizesum > avccontext->extradata_size) {
     58                av_log(avccontext, AV_LOG_ERROR, "vorbis extradata too small\n");
     59                ret = AVERROR_INVALIDDATA;
     60                goto error;
     61            }
     62 
     63            headers[i] = p;
     64            p += hsizes[i];
     65        }
     66    } else if(*p == 2) {
     67        unsigned int offset = 1;
     68        unsigned int sizesum = 1;
     69        p++;
     70        for(i=0; i<2; i++) {
     71            hsizes[i] = 0;
     72            while((*p == 0xFF) && (sizesum < avccontext->extradata_size)) {
     73                hsizes[i] += 0xFF;
     74                offset++;
     75                sizesum += 1 + 0xFF;
     76                p++;
     77            }
     78            hsizes[i] += *p;
     79            offset++;
     80            sizesum += 1 + *p;
     81            if(sizesum > avccontext->extradata_size) {
     82                av_log(avccontext, AV_LOG_ERROR,
     83                       "vorbis header sizes damaged\n");
     84                ret = AVERROR_INVALIDDATA;
     85                goto error;
     86            }
     87            p++;
     88        }
     89        hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset;
     90 #if 0
     91        av_log(avccontext, AV_LOG_DEBUG,
     92               "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
     93               hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size);
     94 #endif
     95        headers[0] = extradata + offset;
     96        headers[1] = extradata + offset + hsizes[0];
     97        headers[2] = extradata + offset + hsizes[0] + hsizes[1];
     98    } else {
     99        av_log(avccontext, AV_LOG_ERROR,
    100               "vorbis initial header len is wrong: %d\n", *p);
    101        ret = AVERROR_INVALIDDATA;
    102        goto error;
    103    }
    104 
    105    for(i=0; i<3; i++){
    106        context->op.b_o_s= i==0;
    107        context->op.bytes = hsizes[i];
    108        context->op.packet = headers[i];
    109        if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
    110            av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
    111            ret = AVERROR_INVALIDDATA;
    112            goto error;
    113        }
    114    }
    115 
    116    av_channel_layout_uninit(&avccontext->ch_layout);
    117    avccontext->ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
    118    avccontext->ch_layout.nb_channels = context->vi.channels;
    119    avccontext->sample_rate = context->vi.rate;
    120    avccontext->sample_fmt = AV_SAMPLE_FMT_S16;
    121    avccontext->time_base= (AVRational){1, avccontext->sample_rate};
    122 
    123    vorbis_synthesis_init(&context->vd, &context->vi);
    124    vorbis_block_init(&context->vd, &context->vb);
    125 
    126    return 0 ;
    127 
    128  error:
    129    oggvorbis_decode_close(avccontext);
    130    return ret;
    131 }
    132 
    133 
    134 static inline int conv(int samples, float **pcm, char *buf, int channels) {
    135    int i, j;
    136    ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;
    137    float *mono ;
    138 
    139    for(i = 0 ; i < channels ; i++){
    140        ptr = &data[i];
    141        mono = pcm[i] ;
    142 
    143        for(j = 0 ; j < samples ; j++) {
    144            *ptr = av_clip_int16(mono[j] * 32767.f);
    145            ptr += channels;
    146        }
    147    }
    148 
    149    return 0 ;
    150 }
    151 
    152 static int oggvorbis_decode_frame(AVCodecContext *avccontext, AVFrame *frame,
    153                                  int *got_frame_ptr, AVPacket *avpkt)
    154 {
    155    OggVorbisDecContext *context = avccontext->priv_data ;
    156    float **pcm ;
    157    ogg_packet *op= &context->op;
    158    int samples, total_samples, total_bytes;
    159    int ret;
    160    int16_t *output;
    161 
    162    if(!avpkt->size){
    163    //FIXME flush
    164        return 0;
    165    }
    166 
    167    frame->nb_samples = 8192*4;
    168    if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0)
    169        return ret;
    170    output = (int16_t *)frame->data[0];
    171 
    172 
    173    op->packet = avpkt->data;
    174    op->bytes  = avpkt->size;
    175 
    176 //    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);
    177 
    178 /*    for(i=0; i<op->bytes; i++)
    179      av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
    180    av_log(avccontext, AV_LOG_DEBUG, "\n");*/
    181 
    182    if(vorbis_synthesis(&context->vb, op) == 0)
    183        vorbis_synthesis_blockin(&context->vd, &context->vb) ;
    184 
    185    total_samples = 0 ;
    186    total_bytes = 0 ;
    187 
    188    while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) {
    189        conv(samples, pcm, (char*)output + total_bytes, context->vi.channels) ;
    190        total_bytes += samples * 2 * context->vi.channels ;
    191        total_samples += samples ;
    192        vorbis_synthesis_read(&context->vd, samples) ;
    193    }
    194 
    195    frame->nb_samples = total_samples;
    196    *got_frame_ptr   = total_samples > 0;
    197    return avpkt->size;
    198 }
    199 
    200 
    201 static int oggvorbis_decode_close(AVCodecContext *avccontext) {
    202    OggVorbisDecContext *context = avccontext->priv_data ;
    203 
    204    vorbis_block_clear(&context->vb);
    205    vorbis_dsp_clear(&context->vd);
    206    vorbis_info_clear(&context->vi) ;
    207    vorbis_comment_clear(&context->vc) ;
    208 
    209    return 0 ;
    210 }
    211 
    212 
    213 const FFCodec ff_libvorbis_decoder = {
    214    .p.name         = "libvorbis",
    215    CODEC_LONG_NAME("libvorbis"),
    216    .p.type         = AVMEDIA_TYPE_AUDIO,
    217    .p.id           = AV_CODEC_ID_VORBIS,
    218    .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF,
    219    .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
    220    .priv_data_size = sizeof(OggVorbisDecContext),
    221    .init           = oggvorbis_decode_init,
    222    FF_CODEC_DECODE_CB(oggvorbis_decode_frame),
    223    .close          = oggvorbis_decode_close,
    224 };