* Copyright (c) 2003 Sascha Sommer
* Copyright (c) 2005 Benjamin Larsson
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
void (* saturate_output) (struct cook *q, int chan, float *out);
AVCodecContext* avctx;
+ AVFrame frame;
GetBitContext gb;
/* stream data */
int nb_channels;
int samples_per_channel;
/* states */
AVLFG random_state;
+ int discarded_packets;
/* transform data */
FFTContext mdct_ctx;
*/
static inline int decode_bytes(const uint8_t* inbuffer, uint8_t* out, int bytes){
+ static const uint32_t tab[4] = {
+ AV_BE2NE32C(0x37c511f2), AV_BE2NE32C(0xf237c511),
+ AV_BE2NE32C(0x11f237c5), AV_BE2NE32C(0xc511f237),
+ };
int i, off;
uint32_t c;
const uint32_t* buf;
off = (intptr_t)inbuffer & 3;
buf = (const uint32_t*) (inbuffer - off);
- c = av_be2ne32((0x37c511f2 >> (off*8)) | (0x37c511f2 << (32-(off*8))));
+ c = tab[off];
bytes += 3 + off;
for (i = 0; i < bytes/4; i++)
obuf[i] = c ^ buf[i];
for(i=0 ; i<q->gain_size_factor ; i++){
buffer[i]*=fc1;
}
- return;
} else { //smooth gain
fc2 = q->gain_table[11 + (gain_index_next-gain_index)];
for(i=0 ; i<q->gain_size_factor ; i++){
buffer[i]*=fc1;
fc1*=fc2;
}
- return;
}
}
* @param decouple_tab decoupling array
*
*/
+static void decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab)
+{
+ int i;
+ int vlc = get_bits1(&q->gb);
+ int start = cplband[p->js_subband_start];
+ int end = cplband[p->subbands-1];
+ int length = end - start + 1;
-static void decouple_info(COOKContext *q, COOKSubpacket *p, int* decouple_tab){
- int length, i;
-
- if(get_bits1(&q->gb)) {
- if(cplband[p->js_subband_start] > cplband[p->subbands-1]) return;
-
- length = cplband[p->subbands-1] - cplband[p->js_subband_start] + 1;
- for (i=0 ; i<length ; i++) {
- decouple_tab[cplband[p->js_subband_start] + i] = get_vlc2(&q->gb, p->ccpl.table, p->ccpl.bits, 2);
- }
+ if (start > end)
return;
- }
-
- if(cplband[p->js_subband_start] > cplband[p->subbands-1]) return;
- length = cplband[p->subbands-1] - cplband[p->js_subband_start] + 1;
- for (i=0 ; i<length ; i++) {
- decouple_tab[cplband[p->js_subband_start] + i] = get_bits(&q->gb, p->js_vlc_bits);
+ if (vlc) {
+ for (i = 0; i < length; i++)
+ decouple_tab[start + i] = get_vlc2(&q->gb, p->ccpl.table, p->ccpl.bits, 2);
+ } else {
+ for (i = 0; i < length; i++)
+ decouple_tab[start + i] = get_bits(&q->gb, p->js_vlc_bits);
}
- return;
}
/*
float *out, int chan)
{
imlt_gain(q, decode_buffer, gains_ptr, previous_buffer);
- q->saturate_output (q, chan, out);
+ if (out)
+ q->saturate_output(q, chan, out);
}
* @param avctx pointer to the AVCodecContext
*/
-static int cook_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
- AVPacket *avpkt) {
+static int cook_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
COOKContext *q = avctx->priv_data;
- int i;
+ float *samples = NULL;
+ int i, ret;
int offset = 0;
int chidx = 0;
if (buf_size < avctx->block_align)
return buf_size;
+ /* get output buffer */
+ if (q->discarded_packets >= 2) {
+ q->frame.nb_samples = q->samples_per_channel;
+ if ((ret = avctx->get_buffer(avctx, &q->frame)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+ samples = (float *)q->frame.data[0];
+ }
+
/* estimate subpacket sizes */
q->subpacket[0].size = avctx->block_align;
}
/* decode supbackets */
- *data_size = 0;
for(i=0;i<q->num_subpackets;i++){
q->subpacket[i].bits_per_subpacket = (q->subpacket[i].size*8)>>q->subpacket[i].bits_per_subpdiv;
q->subpacket[i].ch_idx = chidx;
av_log(avctx,AV_LOG_DEBUG,"subpacket[%i] size %i js %i %i block_align %i\n",i,q->subpacket[i].size,q->subpacket[i].joint_stereo,offset,avctx->block_align);
- decode_subpacket(q, &q->subpacket[i], buf + offset, data);
+ decode_subpacket(q, &q->subpacket[i], buf + offset, samples);
offset += q->subpacket[i].size;
chidx += q->subpacket[i].num_channels;
av_log(avctx,AV_LOG_DEBUG,"subpacket[%i] %i %i\n",i,q->subpacket[i].size * 8,get_bits_count(&q->gb));
}
- *data_size = q->nb_channels * q->samples_per_channel *
- av_get_bytes_per_sample(avctx->sample_fmt);
/* Discard the first two frames: no valid audio. */
- if (avctx->frame_number < 2) *data_size = 0;
+ if (q->discarded_packets < 2) {
+ q->discarded_packets++;
+ *got_frame_ptr = 0;
+ return avctx->block_align;
+ }
+
+ *got_frame_ptr = 1;
+ *(AVFrame *)data = q->frame;
return avctx->block_align;
}
q->subpacket[s].subbands = bytestream_get_be16(&edata_ptr);
extradata_size -= 8;
}
- if (avctx->extradata_size >= 8){
+ if (extradata_size >= 8) {
bytestream_get_be32(&edata_ptr); //Unknown unused
q->subpacket[s].js_subband_start = bytestream_get_be16(&edata_ptr);
q->subpacket[s].js_vlc_bits = bytestream_get_be16(&edata_ptr);
case MONO:
if (q->nb_channels != 1) {
av_log_ask_for_sample(avctx, "Container channels != 1.\n");
- return AVERROR(ENOTSUP);
+ return AVERROR_PATCHWELCOME;
}
av_log(avctx,AV_LOG_DEBUG,"MONO\n");
break;
case JOINT_STEREO:
if (q->nb_channels != 2) {
av_log_ask_for_sample(avctx, "Container channels != 2.\n");
- return AVERROR(ENOTSUP);
+ return AVERROR_PATCHWELCOME;
}
av_log(avctx,AV_LOG_DEBUG,"JOINT_STEREO\n");
if (avctx->extradata_size >= 16){
break;
default:
av_log_ask_for_sample(avctx, "Unknown Cook version.\n");
- return AVERROR(ENOTSUP);
+ return AVERROR_PATCHWELCOME;
}
if(s > 1 && q->subpacket[s].samples_per_channel != q->samples_per_channel) {
/* Try to catch some obviously faulty streams, othervise it might be exploitable */
if (q->subpacket[s].total_subbands > 53) {
av_log_ask_for_sample(avctx, "total_subbands > 53\n");
- return AVERROR(ENOTSUP);
+ return AVERROR_PATCHWELCOME;
}
if ((q->subpacket[s].js_vlc_bits > 6) || (q->subpacket[s].js_vlc_bits < 2*q->subpacket[s].joint_stereo)) {
if (q->subpacket[s].subbands > 50) {
av_log_ask_for_sample(avctx, "subbands > 50\n");
- return AVERROR(ENOTSUP);
+ return AVERROR_PATCHWELCOME;
}
q->subpacket[s].gains1.now = q->subpacket[s].gain_1;
q->subpacket[s].gains1.previous = q->subpacket[s].gain_2;
s++;
if (s > MAX_SUBPACKETS) {
av_log_ask_for_sample(avctx, "Too many subpackets > 5\n");
- return AVERROR(ENOTSUP);
+ return AVERROR_PATCHWELCOME;
}
}
/* Generate tables */
av_log_ask_for_sample(avctx,
"unknown amount of samples_per_channel = %d\n",
q->samples_per_channel);
- return AVERROR(ENOTSUP);
+ return AVERROR_PATCHWELCOME;
}
avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
else
avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
+ avcodec_get_frame_defaults(&q->frame);
+ avctx->coded_frame = &q->frame;
+
#ifdef DEBUG
dump_cook_context(q);
#endif
.init = cook_decode_init,
.close = cook_decode_close,
.decode = cook_decode_frame,
+ .capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("COOK"),
};