Update avcodec to 20080825
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27564 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a687fd7041
commit
bc470b16bf
121
src/add-ons/media/plugins/avcodec/libavcodec/rectangle.h
Normal file
121
src/add-ons/media/plugins/avcodec/libavcodec/rectangle.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* rectangle filling function
|
||||
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file rectangle.h
|
||||
* useful rectangle filling function
|
||||
* @author Michael Niedermayer <michaelni@gmx.at>
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_RECTANGLE_H
|
||||
#define FFMPEG_RECTANGLE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* fill a rectangle.
|
||||
* @param h height of the rectangle, should be a constant
|
||||
* @param w width of the rectangle, should be a constant
|
||||
* @param size the size of val (1 or 4), should be a constant
|
||||
*/
|
||||
static av_always_inline void fill_rectangle(void *vp, int w, int h, int stride, uint32_t val, int size){
|
||||
uint8_t *p= (uint8_t*)vp;
|
||||
assert(size==1 || size==4);
|
||||
assert(w<=4);
|
||||
|
||||
w *= size;
|
||||
stride *= size;
|
||||
|
||||
assert((((long)vp)&(FFMIN(w, STRIDE_ALIGN)-1)) == 0);
|
||||
assert((stride&(w-1))==0);
|
||||
if(w==2){
|
||||
const uint16_t v= size==4 ? val : val*0x0101;
|
||||
*(uint16_t*)(p + 0*stride)= v;
|
||||
if(h==1) return;
|
||||
*(uint16_t*)(p + 1*stride)= v;
|
||||
if(h==2) return;
|
||||
*(uint16_t*)(p + 2*stride)= v;
|
||||
*(uint16_t*)(p + 3*stride)= v;
|
||||
}else if(w==4){
|
||||
const uint32_t v= size==4 ? val : val*0x01010101;
|
||||
*(uint32_t*)(p + 0*stride)= v;
|
||||
if(h==1) return;
|
||||
*(uint32_t*)(p + 1*stride)= v;
|
||||
if(h==2) return;
|
||||
*(uint32_t*)(p + 2*stride)= v;
|
||||
*(uint32_t*)(p + 3*stride)= v;
|
||||
}else if(w==8){
|
||||
//gcc can't optimize 64bit math on x86_32
|
||||
#ifdef HAVE_FAST_64BIT
|
||||
const uint64_t v= val*0x0100000001ULL;
|
||||
*(uint64_t*)(p + 0*stride)= v;
|
||||
if(h==1) return;
|
||||
*(uint64_t*)(p + 1*stride)= v;
|
||||
if(h==2) return;
|
||||
*(uint64_t*)(p + 2*stride)= v;
|
||||
*(uint64_t*)(p + 3*stride)= v;
|
||||
}else if(w==16){
|
||||
const uint64_t v= val*0x0100000001ULL;
|
||||
*(uint64_t*)(p + 0+0*stride)= v;
|
||||
*(uint64_t*)(p + 8+0*stride)= v;
|
||||
*(uint64_t*)(p + 0+1*stride)= v;
|
||||
*(uint64_t*)(p + 8+1*stride)= v;
|
||||
if(h==2) return;
|
||||
*(uint64_t*)(p + 0+2*stride)= v;
|
||||
*(uint64_t*)(p + 8+2*stride)= v;
|
||||
*(uint64_t*)(p + 0+3*stride)= v;
|
||||
*(uint64_t*)(p + 8+3*stride)= v;
|
||||
#else
|
||||
*(uint32_t*)(p + 0+0*stride)= val;
|
||||
*(uint32_t*)(p + 4+0*stride)= val;
|
||||
if(h==1) return;
|
||||
*(uint32_t*)(p + 0+1*stride)= val;
|
||||
*(uint32_t*)(p + 4+1*stride)= val;
|
||||
if(h==2) return;
|
||||
*(uint32_t*)(p + 0+2*stride)= val;
|
||||
*(uint32_t*)(p + 4+2*stride)= val;
|
||||
*(uint32_t*)(p + 0+3*stride)= val;
|
||||
*(uint32_t*)(p + 4+3*stride)= val;
|
||||
}else if(w==16){
|
||||
*(uint32_t*)(p + 0+0*stride)= val;
|
||||
*(uint32_t*)(p + 4+0*stride)= val;
|
||||
*(uint32_t*)(p + 8+0*stride)= val;
|
||||
*(uint32_t*)(p +12+0*stride)= val;
|
||||
*(uint32_t*)(p + 0+1*stride)= val;
|
||||
*(uint32_t*)(p + 4+1*stride)= val;
|
||||
*(uint32_t*)(p + 8+1*stride)= val;
|
||||
*(uint32_t*)(p +12+1*stride)= val;
|
||||
if(h==2) return;
|
||||
*(uint32_t*)(p + 0+2*stride)= val;
|
||||
*(uint32_t*)(p + 4+2*stride)= val;
|
||||
*(uint32_t*)(p + 8+2*stride)= val;
|
||||
*(uint32_t*)(p +12+2*stride)= val;
|
||||
*(uint32_t*)(p + 0+3*stride)= val;
|
||||
*(uint32_t*)(p + 4+3*stride)= val;
|
||||
*(uint32_t*)(p + 8+3*stride)= val;
|
||||
*(uint32_t*)(p +12+3*stride)= val;
|
||||
#endif
|
||||
}else
|
||||
assert(0);
|
||||
assert(h==4);
|
||||
}
|
||||
|
||||
#endif /* FFMPEG_RECTANGLE_H */
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
|
||||
static int remove_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
|
||||
uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size, int keyframe){
|
||||
int cmd= args ? *args : 0;
|
||||
AVCodecParserContext *s;
|
||||
|
||||
if(!bsfc->parser){
|
||||
bsfc->parser= av_parser_init(avctx->codec_id);
|
||||
}
|
||||
s= bsfc->parser;
|
||||
|
||||
if(s && s->parser->split){
|
||||
if( (((avctx->flags & CODEC_FLAG_GLOBAL_HEADER) || (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) && cmd=='a')
|
||||
||(!keyframe && cmd=='k')
|
||||
||(cmd=='e' || !cmd)
|
||||
){
|
||||
int i= s->parser->split(avctx, buf, buf_size);
|
||||
buf += i;
|
||||
buf_size -= i;
|
||||
}
|
||||
}
|
||||
*poutbuf= (uint8_t *) buf;
|
||||
*poutbuf_size= buf_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVBitStreamFilter remove_extradata_bsf={
|
||||
"remove_extra",
|
||||
0,
|
||||
remove_extradata,
|
||||
};
|
@ -1,126 +1,42 @@
|
||||
/*
|
||||
* Sample rate convertion for both audio and video
|
||||
* samplerate conversion for both audio and video
|
||||
* Copyright (c) 2000 Fabrice Bellard.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file resample.c
|
||||
* Sample rate convertion for both audio and video.
|
||||
* samplerate conversion for both audio and video
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
typedef struct {
|
||||
/* fractional resampling */
|
||||
uint32_t incr; /* fractional increment */
|
||||
uint32_t frac;
|
||||
int last_sample;
|
||||
/* integer down sample */
|
||||
int iratio; /* integer divison ratio */
|
||||
int icount, isum;
|
||||
int inv;
|
||||
} ReSampleChannelContext;
|
||||
struct AVResampleContext;
|
||||
|
||||
struct ReSampleContext {
|
||||
ReSampleChannelContext channel_ctx[2];
|
||||
struct AVResampleContext *resample_context;
|
||||
short *temp[2];
|
||||
int temp_len;
|
||||
float ratio;
|
||||
/* channel convert */
|
||||
int input_channels, output_channels, filter_channels;
|
||||
};
|
||||
|
||||
|
||||
#define FRAC_BITS 16
|
||||
#define FRAC (1 << FRAC_BITS)
|
||||
|
||||
static void init_mono_resample(ReSampleChannelContext *s, float ratio)
|
||||
{
|
||||
ratio = 1.0 / ratio;
|
||||
s->iratio = (int)floorf(ratio);
|
||||
if (s->iratio == 0)
|
||||
s->iratio = 1;
|
||||
s->incr = (int)((ratio / s->iratio) * FRAC);
|
||||
s->frac = FRAC;
|
||||
s->last_sample = 0;
|
||||
s->icount = s->iratio;
|
||||
s->isum = 0;
|
||||
s->inv = (FRAC / s->iratio);
|
||||
}
|
||||
|
||||
/* fractional audio resampling */
|
||||
static int fractional_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
|
||||
{
|
||||
unsigned int frac, incr;
|
||||
int l0, l1;
|
||||
short *q, *p, *pend;
|
||||
|
||||
l0 = s->last_sample;
|
||||
incr = s->incr;
|
||||
frac = s->frac;
|
||||
|
||||
p = input;
|
||||
pend = input + nb_samples;
|
||||
q = output;
|
||||
|
||||
l1 = *p++;
|
||||
for(;;) {
|
||||
/* interpolate */
|
||||
*q++ = (l0 * (FRAC - frac) + l1 * frac) >> FRAC_BITS;
|
||||
frac = frac + s->incr;
|
||||
while (frac >= FRAC) {
|
||||
frac -= FRAC;
|
||||
if (p >= pend)
|
||||
goto the_end;
|
||||
l0 = l1;
|
||||
l1 = *p++;
|
||||
}
|
||||
}
|
||||
the_end:
|
||||
s->last_sample = l1;
|
||||
s->frac = frac;
|
||||
return q - output;
|
||||
}
|
||||
|
||||
static int integer_downsample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
|
||||
{
|
||||
short *q, *p, *pend;
|
||||
int c, sum;
|
||||
|
||||
p = input;
|
||||
pend = input + nb_samples;
|
||||
q = output;
|
||||
|
||||
c = s->icount;
|
||||
sum = s->isum;
|
||||
|
||||
for(;;) {
|
||||
sum += *p++;
|
||||
if (--c == 0) {
|
||||
*q++ = (sum * s->inv) >> FRAC_BITS;
|
||||
c = s->iratio;
|
||||
sum = 0;
|
||||
}
|
||||
if (p >= pend)
|
||||
break;
|
||||
}
|
||||
s->isum = sum;
|
||||
s->icount = c;
|
||||
return q - output;
|
||||
}
|
||||
|
||||
/* n1: number of samples */
|
||||
static void stereo_to_mono(short *output, short *input, int n1)
|
||||
{
|
||||
@ -210,77 +126,49 @@ static void ac3_5p1_mux(short *output, short *input1, short *input2, int n)
|
||||
}
|
||||
}
|
||||
|
||||
static int mono_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
|
||||
{
|
||||
short *buf1;
|
||||
short *buftmp;
|
||||
|
||||
buf1= (short*)av_malloc( nb_samples * sizeof(short) );
|
||||
|
||||
/* first downsample by an integer factor with averaging filter */
|
||||
if (s->iratio > 1) {
|
||||
buftmp = buf1;
|
||||
nb_samples = integer_downsample(s, buftmp, input, nb_samples);
|
||||
} else {
|
||||
buftmp = input;
|
||||
}
|
||||
|
||||
/* then do a fractional resampling with linear interpolation */
|
||||
if (s->incr != FRAC) {
|
||||
nb_samples = fractional_resample(s, output, buftmp, nb_samples);
|
||||
} else {
|
||||
memcpy(output, buftmp, nb_samples * sizeof(short));
|
||||
}
|
||||
av_free(buf1);
|
||||
return nb_samples;
|
||||
}
|
||||
|
||||
ReSampleContext *audio_resample_init(int output_channels, int input_channels,
|
||||
ReSampleContext *audio_resample_init(int output_channels, int input_channels,
|
||||
int output_rate, int input_rate)
|
||||
{
|
||||
ReSampleContext *s;
|
||||
int i;
|
||||
|
||||
|
||||
if ( input_channels > 2)
|
||||
{
|
||||
av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported.");
|
||||
return NULL;
|
||||
av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = av_mallocz(sizeof(ReSampleContext));
|
||||
if (!s)
|
||||
{
|
||||
av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context.");
|
||||
return NULL;
|
||||
av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->ratio = (float)output_rate / (float)input_rate;
|
||||
|
||||
|
||||
s->input_channels = input_channels;
|
||||
s->output_channels = output_channels;
|
||||
|
||||
|
||||
s->filter_channels = s->input_channels;
|
||||
if (s->output_channels < s->filter_channels)
|
||||
s->filter_channels = s->output_channels;
|
||||
|
||||
/*
|
||||
* ac3 output is the only case where filter_channels could be greater than 2.
|
||||
* AC-3 output is the only case where filter_channels could be greater than 2.
|
||||
* input channels can't be greater than 2, so resample the 2 channels and then
|
||||
* expand to 6 channels after the resampling.
|
||||
*/
|
||||
if(s->filter_channels>2)
|
||||
s->filter_channels = 2;
|
||||
|
||||
for(i=0;i<s->filter_channels;i++) {
|
||||
init_mono_resample(&s->channel_ctx[i], s->ratio);
|
||||
}
|
||||
#define TAPS 16
|
||||
s->resample_context= av_resample_init(output_rate, input_rate, TAPS, 10, 0, 0.8);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* resample audio. 'nb_samples' is the number of input samples */
|
||||
/* XXX: optimize it ! */
|
||||
/* XXX: do it with polyphase filters, since the quality here is
|
||||
HORRIBLE. Return the number of samples available in output */
|
||||
int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples)
|
||||
{
|
||||
int i, nb_samples1;
|
||||
@ -289,44 +177,52 @@ int audio_resample(ReSampleContext *s, short *output, short *input, int nb_sampl
|
||||
short *buftmp2[2], *buftmp3[2];
|
||||
int lenout;
|
||||
|
||||
if (s->input_channels == s->output_channels && s->ratio == 1.0) {
|
||||
if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) {
|
||||
/* nothing to do */
|
||||
memcpy(output, input, nb_samples * s->input_channels * sizeof(short));
|
||||
return nb_samples;
|
||||
}
|
||||
|
||||
/* XXX: move those malloc to resample init code */
|
||||
bufin[0]= (short*) av_malloc( nb_samples * sizeof(short) );
|
||||
bufin[1]= (short*) av_malloc( nb_samples * sizeof(short) );
|
||||
|
||||
for(i=0; i<s->filter_channels; i++){
|
||||
bufin[i]= av_malloc( (nb_samples + s->temp_len) * sizeof(short) );
|
||||
memcpy(bufin[i], s->temp[i], s->temp_len * sizeof(short));
|
||||
buftmp2[i] = bufin[i] + s->temp_len;
|
||||
}
|
||||
|
||||
/* make some zoom to avoid round pb */
|
||||
lenout= (int)(nb_samples * s->ratio) + 16;
|
||||
bufout[0]= (short*) av_malloc( lenout * sizeof(short) );
|
||||
bufout[1]= (short*) av_malloc( lenout * sizeof(short) );
|
||||
lenout= 4*nb_samples * s->ratio + 16;
|
||||
bufout[0]= av_malloc( lenout * sizeof(short) );
|
||||
bufout[1]= av_malloc( lenout * sizeof(short) );
|
||||
|
||||
if (s->input_channels == 2 &&
|
||||
s->output_channels == 1) {
|
||||
buftmp2[0] = bufin[0];
|
||||
buftmp3[0] = output;
|
||||
stereo_to_mono(buftmp2[0], input, nb_samples);
|
||||
} else if (s->output_channels >= 2 && s->input_channels == 1) {
|
||||
buftmp2[0] = input;
|
||||
buftmp3[0] = bufout[0];
|
||||
memcpy(buftmp2[0], input, nb_samples*sizeof(short));
|
||||
} else if (s->output_channels >= 2) {
|
||||
buftmp2[0] = bufin[0];
|
||||
buftmp2[1] = bufin[1];
|
||||
buftmp3[0] = bufout[0];
|
||||
buftmp3[1] = bufout[1];
|
||||
stereo_split(buftmp2[0], buftmp2[1], input, nb_samples);
|
||||
} else {
|
||||
buftmp2[0] = input;
|
||||
buftmp3[0] = output;
|
||||
memcpy(buftmp2[0], input, nb_samples*sizeof(short));
|
||||
}
|
||||
|
||||
nb_samples += s->temp_len;
|
||||
|
||||
/* resample each channel */
|
||||
nb_samples1 = 0; /* avoid warning */
|
||||
for(i=0;i<s->filter_channels;i++) {
|
||||
nb_samples1 = mono_resample(&s->channel_ctx[i], buftmp3[i], buftmp2[i], nb_samples);
|
||||
int consumed;
|
||||
int is_last= i+1 == s->filter_channels;
|
||||
|
||||
nb_samples1 = av_resample(s->resample_context, buftmp3[i], bufin[i], &consumed, nb_samples, lenout, is_last);
|
||||
s->temp_len= nb_samples - consumed;
|
||||
s->temp[i]= av_realloc(s->temp[i], s->temp_len*sizeof(short));
|
||||
memcpy(s->temp[i], bufin[i] + consumed, s->temp_len*sizeof(short));
|
||||
}
|
||||
|
||||
if (s->output_channels == 2 && s->input_channels == 1) {
|
||||
@ -337,8 +233,8 @@ int audio_resample(ReSampleContext *s, short *output, short *input, int nb_sampl
|
||||
ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1);
|
||||
}
|
||||
|
||||
av_free(bufin[0]);
|
||||
av_free(bufin[1]);
|
||||
for(i=0; i<s->filter_channels; i++)
|
||||
av_free(bufin[i]);
|
||||
|
||||
av_free(bufout[0]);
|
||||
av_free(bufout[1]);
|
||||
@ -347,5 +243,8 @@ int audio_resample(ReSampleContext *s, short *output, short *input, int nb_sampl
|
||||
|
||||
void audio_resample_close(ReSampleContext *s)
|
||||
{
|
||||
av_resample_close(s->resample_context);
|
||||
av_freep(&s->temp[0]);
|
||||
av_freep(&s->temp[1]);
|
||||
av_free(s);
|
||||
}
|
||||
|
324
src/add-ons/media/plugins/avcodec/libavcodec/resample2.c
Normal file
324
src/add-ons/media/plugins/avcodec/libavcodec/resample2.c
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* audio resampling
|
||||
* Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file resample2.c
|
||||
* audio resampling
|
||||
* @author Michael Niedermayer <michaelni@gmx.at>
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "dsputil.h"
|
||||
|
||||
#ifndef CONFIG_RESAMPLE_HP
|
||||
#define FILTER_SHIFT 15
|
||||
|
||||
#define FELEM int16_t
|
||||
#define FELEM2 int32_t
|
||||
#define FELEML int64_t
|
||||
#define FELEM_MAX INT16_MAX
|
||||
#define FELEM_MIN INT16_MIN
|
||||
#define WINDOW_TYPE 9
|
||||
#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE)
|
||||
#define FILTER_SHIFT 30
|
||||
|
||||
#define FELEM int32_t
|
||||
#define FELEM2 int64_t
|
||||
#define FELEML int64_t
|
||||
#define FELEM_MAX INT32_MAX
|
||||
#define FELEM_MIN INT32_MIN
|
||||
#define WINDOW_TYPE 12
|
||||
#else
|
||||
#define FILTER_SHIFT 0
|
||||
|
||||
#define FELEM double
|
||||
#define FELEM2 double
|
||||
#define FELEML double
|
||||
#define WINDOW_TYPE 24
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct AVResampleContext{
|
||||
FELEM *filter_bank;
|
||||
int filter_length;
|
||||
int ideal_dst_incr;
|
||||
int dst_incr;
|
||||
int index;
|
||||
int frac;
|
||||
int src_incr;
|
||||
int compensation_distance;
|
||||
int phase_shift;
|
||||
int phase_mask;
|
||||
int linear;
|
||||
}AVResampleContext;
|
||||
|
||||
/**
|
||||
* 0th order modified bessel function of the first kind.
|
||||
*/
|
||||
static double bessel(double x){
|
||||
double v=1;
|
||||
double t=1;
|
||||
int i;
|
||||
|
||||
x= x*x/4;
|
||||
for(i=1; i<50; i++){
|
||||
t *= x/(i*i);
|
||||
v += t;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* builds a polyphase filterbank.
|
||||
* @param factor resampling factor
|
||||
* @param scale wanted sum of coefficients for each filter
|
||||
* @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16
|
||||
*/
|
||||
void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){
|
||||
int ph, i;
|
||||
double x, y, w, tab[tap_count];
|
||||
const int center= (tap_count-1)/2;
|
||||
|
||||
/* if upsampling, only need to interpolate, no filter */
|
||||
if (factor > 1.0)
|
||||
factor = 1.0;
|
||||
|
||||
for(ph=0;ph<phase_count;ph++) {
|
||||
double norm = 0;
|
||||
for(i=0;i<tap_count;i++) {
|
||||
x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
|
||||
if (x == 0) y = 1.0;
|
||||
else y = sin(x) / x;
|
||||
switch(type){
|
||||
case 0:{
|
||||
const float d= -0.5; //first order derivative = -0.5
|
||||
x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
|
||||
if(x<1.0) y= 1 - 3*x*x + 2*x*x*x + d*( -x*x + x*x*x);
|
||||
else y= d*(-4 + 8*x - 5*x*x + x*x*x);
|
||||
break;}
|
||||
case 1:
|
||||
w = 2.0*x / (factor*tap_count) + M_PI;
|
||||
y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w);
|
||||
break;
|
||||
default:
|
||||
w = 2.0*x / (factor*tap_count*M_PI);
|
||||
y *= bessel(type*sqrt(FFMAX(1-w*w, 0)));
|
||||
break;
|
||||
}
|
||||
|
||||
tab[i] = y;
|
||||
norm += y;
|
||||
}
|
||||
|
||||
/* normalize so that an uniform color remains the same */
|
||||
for(i=0;i<tap_count;i++) {
|
||||
#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
|
||||
filter[ph * tap_count + i] = tab[i] / norm;
|
||||
#else
|
||||
filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm), FELEM_MIN, FELEM_MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
#define LEN 1024
|
||||
int j,k;
|
||||
double sine[LEN + tap_count];
|
||||
double filtered[LEN];
|
||||
double maxff=-2, minff=2, maxsf=-2, minsf=2;
|
||||
for(i=0; i<LEN; i++){
|
||||
double ss=0, sf=0, ff=0;
|
||||
for(j=0; j<LEN+tap_count; j++)
|
||||
sine[j]= cos(i*j*M_PI/LEN);
|
||||
for(j=0; j<LEN; j++){
|
||||
double sum=0;
|
||||
ph=0;
|
||||
for(k=0; k<tap_count; k++)
|
||||
sum += filter[ph * tap_count + k] * sine[k+j];
|
||||
filtered[j]= sum / (1<<FILTER_SHIFT);
|
||||
ss+= sine[j + center] * sine[j + center];
|
||||
ff+= filtered[j] * filtered[j];
|
||||
sf+= sine[j + center] * filtered[j];
|
||||
}
|
||||
ss= sqrt(2*ss/LEN);
|
||||
ff= sqrt(2*ff/LEN);
|
||||
sf= 2*sf/LEN;
|
||||
maxff= FFMAX(maxff, ff);
|
||||
minff= FFMIN(minff, ff);
|
||||
maxsf= FFMAX(maxsf, sf);
|
||||
minsf= FFMIN(minsf, sf);
|
||||
if(i%11==0){
|
||||
av_log(NULL, AV_LOG_ERROR, "i:%4d ss:%f ff:%13.6e-%13.6e sf:%13.6e-%13.6e\n", i, ss, maxff, minff, maxsf, minsf);
|
||||
minff=minsf= 2;
|
||||
maxff=maxsf= -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an audio resampler.
|
||||
* Note, if either rate is not an integer then simply scale both rates up so they are.
|
||||
*/
|
||||
AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff){
|
||||
AVResampleContext *c= av_mallocz(sizeof(AVResampleContext));
|
||||
double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
|
||||
int phase_count= 1<<phase_shift;
|
||||
|
||||
c->phase_shift= phase_shift;
|
||||
c->phase_mask= phase_count-1;
|
||||
c->linear= linear;
|
||||
|
||||
c->filter_length= FFMAX((int)ceil(filter_size/factor), 1);
|
||||
c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM));
|
||||
av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, WINDOW_TYPE);
|
||||
memcpy(&c->filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM));
|
||||
c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1];
|
||||
|
||||
c->src_incr= out_rate;
|
||||
c->ideal_dst_incr= c->dst_incr= in_rate * phase_count;
|
||||
c->index= -phase_count*((c->filter_length-1)/2);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void av_resample_close(AVResampleContext *c){
|
||||
av_freep(&c->filter_bank);
|
||||
av_freep(&c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compensates samplerate/timestamp drift. The compensation is done by changing
|
||||
* the resampler parameters, so no audible clicks or similar distortions occur
|
||||
* @param compensation_distance distance in output samples over which the compensation should be performed
|
||||
* @param sample_delta number of output samples which should be output less
|
||||
*
|
||||
* example: av_resample_compensate(c, 10, 500)
|
||||
* here instead of 510 samples only 500 samples would be output
|
||||
*
|
||||
* note, due to rounding the actual compensation might be slightly different,
|
||||
* especially if the compensation_distance is large and the in_rate used during init is small
|
||||
*/
|
||||
void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){
|
||||
// sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr;
|
||||
c->compensation_distance= compensation_distance;
|
||||
c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* resamples.
|
||||
* @param src an array of unconsumed samples
|
||||
* @param consumed the number of samples of src which have been consumed are returned here
|
||||
* @param src_size the number of unconsumed samples available
|
||||
* @param dst_size the amount of space in samples available in dst
|
||||
* @param update_ctx If this is 0 then the context will not be modified, that way several channels can be resampled with the same context.
|
||||
* @return the number of samples written in dst or -1 if an error occurred
|
||||
*/
|
||||
int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){
|
||||
int dst_index, i;
|
||||
int index= c->index;
|
||||
int frac= c->frac;
|
||||
int dst_incr_frac= c->dst_incr % c->src_incr;
|
||||
int dst_incr= c->dst_incr / c->src_incr;
|
||||
int compensation_distance= c->compensation_distance;
|
||||
|
||||
if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){
|
||||
int64_t index2= ((int64_t)index)<<32;
|
||||
int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr;
|
||||
dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr);
|
||||
|
||||
for(dst_index=0; dst_index < dst_size; dst_index++){
|
||||
dst[dst_index] = src[index2>>32];
|
||||
index2 += incr;
|
||||
}
|
||||
frac += dst_index * dst_incr_frac;
|
||||
index += dst_index * dst_incr;
|
||||
index += frac / c->src_incr;
|
||||
frac %= c->src_incr;
|
||||
}else{
|
||||
for(dst_index=0; dst_index < dst_size; dst_index++){
|
||||
FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask);
|
||||
int sample_index= index >> c->phase_shift;
|
||||
FELEM2 val=0;
|
||||
|
||||
if(sample_index < 0){
|
||||
for(i=0; i<c->filter_length; i++)
|
||||
val += src[FFABS(sample_index + i) % src_size] * filter[i];
|
||||
}else if(sample_index + c->filter_length > src_size){
|
||||
break;
|
||||
}else if(c->linear){
|
||||
FELEM2 v2=0;
|
||||
for(i=0; i<c->filter_length; i++){
|
||||
val += src[sample_index + i] * (FELEM2)filter[i];
|
||||
v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length];
|
||||
}
|
||||
val+=(v2-val)*(FELEML)frac / c->src_incr;
|
||||
}else{
|
||||
for(i=0; i<c->filter_length; i++){
|
||||
val += src[sample_index + i] * (FELEM2)filter[i];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
|
||||
dst[dst_index] = av_clip_int16(lrintf(val));
|
||||
#else
|
||||
val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
|
||||
dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val;
|
||||
#endif
|
||||
|
||||
frac += dst_incr_frac;
|
||||
index += dst_incr;
|
||||
if(frac >= c->src_incr){
|
||||
frac -= c->src_incr;
|
||||
index++;
|
||||
}
|
||||
|
||||
if(dst_index + 1 == compensation_distance){
|
||||
compensation_distance= 0;
|
||||
dst_incr_frac= c->ideal_dst_incr % c->src_incr;
|
||||
dst_incr= c->ideal_dst_incr / c->src_incr;
|
||||
}
|
||||
}
|
||||
}
|
||||
*consumed= FFMAX(index, 0) >> c->phase_shift;
|
||||
if(index>=0) index &= c->phase_mask;
|
||||
|
||||
if(compensation_distance){
|
||||
compensation_distance -= dst_index;
|
||||
assert(compensation_distance > 0);
|
||||
}
|
||||
if(update_ctx){
|
||||
c->frac= frac;
|
||||
c->index= index;
|
||||
c->dst_incr= dst_incr_frac + c->src_incr*dst_incr;
|
||||
c->compensation_distance= compensation_distance;
|
||||
}
|
||||
#if 0
|
||||
if(update_ctx && !c->compensation_distance){
|
||||
#undef rand
|
||||
av_resample_compensate(c, rand() % (8000*2) - 8000, 8000*2);
|
||||
av_log(NULL, AV_LOG_DEBUG, "%d %d %d\n", c->dst_incr, c->ideal_dst_incr, c->compensation_distance);
|
||||
}
|
||||
#endif
|
||||
|
||||
return dst_index;
|
||||
}
|
86
src/add-ons/media/plugins/avcodec/libavcodec/rl.h
Normal file
86
src/add-ons/media/plugins/avcodec/libavcodec/rl.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2002 Fabrice Bellard
|
||||
* Copyright (c) 2002-2004 Michael Niedermayer
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file rl.h
|
||||
* rl header.
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_RL_H
|
||||
#define FFMPEG_RL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bitstream.h"
|
||||
|
||||
/* run length table */
|
||||
#define MAX_RUN 64
|
||||
#define MAX_LEVEL 64
|
||||
|
||||
/** RLTable. */
|
||||
typedef struct RLTable {
|
||||
int n; ///< number of entries of table_vlc minus 1
|
||||
int last; ///< number of values for last = 0
|
||||
const uint16_t (*table_vlc)[2];
|
||||
const int8_t *table_run;
|
||||
const int8_t *table_level;
|
||||
uint8_t *index_run[2]; ///< encoding only
|
||||
int8_t *max_level[2]; ///< encoding & decoding
|
||||
int8_t *max_run[2]; ///< encoding & decoding
|
||||
VLC vlc; ///< decoding only deprecated FIXME remove
|
||||
RL_VLC_ELEM *rl_vlc[32]; ///< decoding only
|
||||
} RLTable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param static_store static uint8_t array[2][2*MAX_RUN + MAX_LEVEL + 3] which will hold
|
||||
* the level and run tables, if this is NULL av_malloc() will be used
|
||||
*/
|
||||
void init_rl(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3]);
|
||||
void init_vlc_rl(RLTable *rl);
|
||||
|
||||
#define INIT_VLC_RL(rl, static_size)\
|
||||
{\
|
||||
int q;\
|
||||
static RL_VLC_ELEM rl_vlc_table[32][static_size];\
|
||||
INIT_VLC_STATIC(&rl.vlc, 9, rl.n + 1,\
|
||||
&rl.table_vlc[0][1], 4, 2,\
|
||||
&rl.table_vlc[0][0], 4, 2, static_size);\
|
||||
\
|
||||
if(!rl.rl_vlc[0]){\
|
||||
for(q=0; q<32; q++)\
|
||||
rl.rl_vlc[q]= rl_vlc_table[q];\
|
||||
\
|
||||
init_vlc_rl(&rl);\
|
||||
}\
|
||||
}
|
||||
|
||||
static inline int get_rl_index(const RLTable *rl, int last, int run, int level)
|
||||
{
|
||||
int index;
|
||||
index = rl->index_run[last][run];
|
||||
if (index >= rl->n)
|
||||
return rl->n;
|
||||
if (level > rl->max_level[last][run])
|
||||
return rl->n;
|
||||
return index + level - 1;
|
||||
}
|
||||
|
||||
#endif /* FFMPEG_RL_H */
|
241
src/add-ons/media/plugins/avcodec/libavcodec/rl2.c
Normal file
241
src/add-ons/media/plugins/avcodec/libavcodec/rl2.c
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* RL2 Video Decoder
|
||||
* Copyright (C) 2008 Sascha Sommer (saschasommer@freenet.de)
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* RL2 Video Decoder
|
||||
* @file rl2.c
|
||||
* @author Sascha Sommer (saschasommer@freenet.de)
|
||||
* For more information about the RL2 format, visit:
|
||||
* http://wiki.multimedia.cx/index.php?title=RL2
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
|
||||
#define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr count, palette
|
||||
|
||||
typedef struct Rl2Context {
|
||||
AVCodecContext *avctx;
|
||||
AVFrame frame;
|
||||
|
||||
unsigned short video_base; ///< initial drawing offset
|
||||
unsigned int clr_count; ///< number of used colors (currently unused)
|
||||
unsigned char* back_frame; ///< background frame
|
||||
unsigned int palette[AVPALETTE_COUNT];
|
||||
} Rl2Context;
|
||||
|
||||
/**
|
||||
* Run Length Decode a single 320x200 frame
|
||||
* @param s rl2 context
|
||||
* @param buf input buffer
|
||||
* @param size input buffer size
|
||||
* @param out ouput buffer
|
||||
* @param stride stride of the output buffer
|
||||
* @param video_base offset of the rle data inside the frame
|
||||
*/
|
||||
static void rl2_rle_decode(Rl2Context *s,const unsigned char* in,int size,
|
||||
unsigned char* out,int stride,int video_base){
|
||||
int base_x = video_base % s->avctx->width;
|
||||
int base_y = video_base / s->avctx->width;
|
||||
int stride_adj = stride - s->avctx->width;
|
||||
int i;
|
||||
const unsigned char* back_frame = s->back_frame;
|
||||
const unsigned char* in_end = in + size;
|
||||
const unsigned char* out_end = out + stride * s->avctx->height;
|
||||
unsigned char* line_end = out + s->avctx->width;
|
||||
|
||||
/** copy start of the background frame */
|
||||
for(i=0;i<=base_y;i++){
|
||||
if(s->back_frame)
|
||||
memcpy(out,back_frame,s->avctx->width);
|
||||
out += stride;
|
||||
back_frame += s->avctx->width;
|
||||
}
|
||||
back_frame += base_x - s->avctx->width;
|
||||
line_end = out - stride_adj;
|
||||
out += base_x - stride;
|
||||
|
||||
/** decode the variable part of the frame */
|
||||
while(in < in_end){
|
||||
unsigned char val = *in++;
|
||||
int len = 1;
|
||||
if(val >= 0x80){
|
||||
if(in >= in_end)
|
||||
break;
|
||||
len = *in++;
|
||||
if(!len)
|
||||
break;
|
||||
}
|
||||
|
||||
if(len >= out_end - out)
|
||||
break;
|
||||
|
||||
if(s->back_frame)
|
||||
val |= 0x80;
|
||||
else
|
||||
val &= ~0x80;
|
||||
|
||||
while(len--){
|
||||
*out++ = (val == 0x80)? *back_frame:val;
|
||||
back_frame++;
|
||||
if(out == line_end){
|
||||
out += stride_adj;
|
||||
line_end += stride;
|
||||
if(len >= out_end - out)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** copy the rest from the background frame */
|
||||
if(s->back_frame){
|
||||
while(out < out_end){
|
||||
memcpy(out, back_frame, line_end - out);
|
||||
back_frame += line_end - out;
|
||||
out = line_end + stride_adj;
|
||||
line_end += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the decoder
|
||||
* @param avctx decoder context
|
||||
* @return 0 success, -1 on error
|
||||
*/
|
||||
static av_cold int rl2_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
Rl2Context *s = avctx->priv_data;
|
||||
int back_size;
|
||||
int i;
|
||||
s->avctx = avctx;
|
||||
avctx->pix_fmt = PIX_FMT_PAL8;
|
||||
|
||||
/** parse extra data */
|
||||
if(!avctx->extradata || avctx->extradata_size < EXTRADATA1_SIZE){
|
||||
av_log(avctx, AV_LOG_ERROR, "invalid extradata size\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** get frame_offset */
|
||||
s->video_base = AV_RL16(&avctx->extradata[0]);
|
||||
s->clr_count = AV_RL32(&avctx->extradata[2]);
|
||||
|
||||
if(s->video_base >= avctx->width * avctx->height){
|
||||
av_log(avctx, AV_LOG_ERROR, "invalid video_base\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** initialize palette */
|
||||
for(i=0;i<AVPALETTE_COUNT;i++)
|
||||
s->palette[i] = AV_RB24(&avctx->extradata[6 + i * 3]);
|
||||
|
||||
/** decode background frame if present */
|
||||
back_size = avctx->extradata_size - EXTRADATA1_SIZE;
|
||||
|
||||
if(back_size > 0){
|
||||
unsigned char* back_frame = av_mallocz(avctx->width*avctx->height);
|
||||
if(!back_frame)
|
||||
return -1;
|
||||
rl2_rle_decode(s,avctx->extradata + EXTRADATA1_SIZE,back_size,
|
||||
back_frame,avctx->width,0);
|
||||
s->back_frame = back_frame;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decode a single frame
|
||||
* @param avctx decoder context
|
||||
* @param data decoded frame
|
||||
* @param data_size size of the decoded frame
|
||||
* @param buf input buffer
|
||||
* @param buf_size input buffer size
|
||||
* @return 0 success, -1 on error
|
||||
*/
|
||||
static int rl2_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
Rl2Context *s = avctx->priv_data;
|
||||
|
||||
if(s->frame.data[0])
|
||||
avctx->release_buffer(avctx, &s->frame);
|
||||
|
||||
/** get buffer */
|
||||
s->frame.reference= 0;
|
||||
if(avctx->get_buffer(avctx, &s->frame)) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** run length decode */
|
||||
rl2_rle_decode(s,buf,buf_size,s->frame.data[0],s->frame.linesize[0],s->video_base);
|
||||
|
||||
/** make the palette available on the way out */
|
||||
memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
|
||||
|
||||
*data_size = sizeof(AVFrame);
|
||||
*(AVFrame*)data = s->frame;
|
||||
|
||||
/** report that the buffer was completely consumed */
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uninit decoder
|
||||
* @param avctx decoder context
|
||||
* @return 0 success, -1 on error
|
||||
*/
|
||||
static av_cold int rl2_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
Rl2Context *s = avctx->priv_data;
|
||||
|
||||
if(s->frame.data[0])
|
||||
avctx->release_buffer(avctx, &s->frame);
|
||||
|
||||
av_free(s->back_frame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AVCodec rl2_decoder = {
|
||||
"rl2",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_RL2,
|
||||
sizeof(Rl2Context),
|
||||
rl2_decode_init,
|
||||
NULL,
|
||||
rl2_decode_end,
|
||||
rl2_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("RL2 video"),
|
||||
};
|
||||
|
84
src/add-ons/media/plugins/avcodec/libavcodec/rle.c
Normal file
84
src/add-ons/media/plugins/avcodec/libavcodec/rle.c
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* RLE encoder
|
||||
* Copyright (c) 2007 Bobby Bingham
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "avcodec.h"
|
||||
#include "rle.h"
|
||||
|
||||
/**
|
||||
* Count up to 127 consecutive pixels which are either all the same or
|
||||
* all differ from the previous and next pixels.
|
||||
* @param start Pointer to the first pixel
|
||||
* @param len Maximum number of pixels
|
||||
* @param bpp Bytes per pixel
|
||||
* @param same 1 if searching for identical pixel values. 0 for differing
|
||||
* @return Number of matching consecutive pixels found
|
||||
*/
|
||||
static int count_pixels(const uint8_t *start, int len, int bpp, int same)
|
||||
{
|
||||
const uint8_t *pos;
|
||||
int count = 1;
|
||||
|
||||
for(pos = start + bpp; count < FFMIN(127, len); pos += bpp, count ++) {
|
||||
if(same != !memcmp(pos-bpp, pos, bpp)) {
|
||||
if(!same) {
|
||||
/* if bpp == 1, then 0 1 1 0 is more efficiently encoded as a single
|
||||
* raw block of pixels. for larger bpp, RLE is as good or better */
|
||||
if(bpp == 1 && count + 1 < FFMIN(127, len) && *pos != *(pos+1))
|
||||
continue;
|
||||
|
||||
/* if RLE can encode the next block better than as a raw block,
|
||||
* back up and leave _all_ the identical pixels for RLE */
|
||||
count --;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *ptr , int bpp, int w,
|
||||
int add_rep, int xor_rep, int add_raw, int xor_raw)
|
||||
{
|
||||
int count, x;
|
||||
uint8_t *out = outbuf;
|
||||
|
||||
for(x = 0; x < w; x += count) {
|
||||
/* see if we can encode the next set of pixels with RLE */
|
||||
if((count = count_pixels(ptr, w-x, bpp, 1)) > 1) {
|
||||
if(out + bpp + 1 > outbuf + out_size) return -1;
|
||||
*out++ = (count ^ xor_rep) + add_rep;
|
||||
memcpy(out, ptr, bpp);
|
||||
out += bpp;
|
||||
} else {
|
||||
/* fall back on uncompressed */
|
||||
count = count_pixels(ptr, w-x, bpp, 0);
|
||||
if(out + bpp*count >= outbuf + out_size) return -1;
|
||||
*out++ = (count ^ xor_raw) + add_raw;
|
||||
|
||||
memcpy(out, ptr, bpp * count);
|
||||
out += bpp * count;
|
||||
}
|
||||
|
||||
ptr += count * bpp;
|
||||
}
|
||||
|
||||
return out - outbuf;
|
||||
}
|
39
src/add-ons/media/plugins/avcodec/libavcodec/rle.h
Normal file
39
src/add-ons/media/plugins/avcodec/libavcodec/rle.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* RLE encoder
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_RLE_H
|
||||
#define FFMPEG_RLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* RLE compress the row, with maximum size of out_size. Value before repeated bytes is (count ^ xor_rep) + add_rep.
|
||||
* Value before raw bytes is (count ^ xor_raw) + add_raw.
|
||||
* @param outbuf Output buffer
|
||||
* @param out_size Maximum output size
|
||||
* @param ptr Input buffer
|
||||
* @param bpp Bytes per pixel
|
||||
* @param w Image width
|
||||
* @return Size of output in bytes, or -1 if larger than out_size
|
||||
*/
|
||||
int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *inbuf, int bpp, int w,
|
||||
int add_rep, int xor_rep, int add_raw, int xor_raw);
|
||||
|
||||
#endif /* FFMPEG_RLE_H */
|
179
src/add-ons/media/plugins/avcodec/libavcodec/roqaudioenc.c
Normal file
179
src/add-ons/media/plugins/avcodec/libavcodec/roqaudioenc.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* RoQ audio encoder
|
||||
*
|
||||
* Copyright (c) 2005 Eric Lasota
|
||||
* Based on RoQ specs (c)2001 Tim Ferguson
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
|
||||
#define ROQ_FIRST_FRAME_SIZE (735*8)
|
||||
#define ROQ_FRAME_SIZE 735
|
||||
|
||||
|
||||
#define MAX_DPCM (127*127)
|
||||
static unsigned char dpcmValues[MAX_DPCM];
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short lastSample[2];
|
||||
} ROQDPCMContext_t;
|
||||
|
||||
static av_cold void roq_dpcm_table_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Create a table of quick DPCM values */
|
||||
for (i=0; i<MAX_DPCM; i++) {
|
||||
int s= ff_sqrt(i);
|
||||
int mid= s*s + s;
|
||||
dpcmValues[i]= s + (i>mid);
|
||||
}
|
||||
}
|
||||
|
||||
static int roq_dpcm_encode_init(AVCodecContext *avctx)
|
||||
{
|
||||
ROQDPCMContext_t *context = avctx->priv_data;
|
||||
|
||||
if (avctx->channels > 2) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n");
|
||||
return -1;
|
||||
}
|
||||
if (avctx->sample_rate != 22050) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n");
|
||||
return -1;
|
||||
}
|
||||
if (avctx->sample_fmt != SAMPLE_FMT_S16) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Audio must be signed 16-bit\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
roq_dpcm_table_init();
|
||||
|
||||
avctx->frame_size = ROQ_FIRST_FRAME_SIZE;
|
||||
|
||||
context->lastSample[0] = context->lastSample[1] = 0;
|
||||
|
||||
avctx->coded_frame= avcodec_alloc_frame();
|
||||
avctx->coded_frame->key_frame= 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned char dpcm_predict(short *previous, short current)
|
||||
{
|
||||
int diff;
|
||||
int negative;
|
||||
int result;
|
||||
int predicted;
|
||||
|
||||
diff = current - *previous;
|
||||
|
||||
negative = diff<0;
|
||||
diff = FFABS(diff);
|
||||
|
||||
if (diff >= MAX_DPCM)
|
||||
result = 127;
|
||||
else
|
||||
result = dpcmValues[diff];
|
||||
|
||||
/* See if this overflows */
|
||||
retry:
|
||||
diff = result*result;
|
||||
if (negative)
|
||||
diff = -diff;
|
||||
predicted = *previous + diff;
|
||||
|
||||
/* If it overflows, back off a step */
|
||||
if (predicted > 32767 || predicted < -32768) {
|
||||
result--;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Add the sign bit */
|
||||
result |= negative << 7; //if (negative) result |= 128;
|
||||
|
||||
*previous = predicted;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int roq_dpcm_encode_frame(AVCodecContext *avctx,
|
||||
unsigned char *frame, int buf_size, void *data)
|
||||
{
|
||||
int i, samples, stereo, ch;
|
||||
short *in;
|
||||
unsigned char *out;
|
||||
|
||||
ROQDPCMContext_t *context = avctx->priv_data;
|
||||
|
||||
stereo = (avctx->channels == 2);
|
||||
|
||||
if (stereo) {
|
||||
context->lastSample[0] &= 0xFF00;
|
||||
context->lastSample[1] &= 0xFF00;
|
||||
}
|
||||
|
||||
out = frame;
|
||||
in = data;
|
||||
|
||||
bytestream_put_byte(&out, stereo ? 0x21 : 0x20);
|
||||
bytestream_put_byte(&out, 0x10);
|
||||
bytestream_put_le32(&out, avctx->frame_size*avctx->channels);
|
||||
|
||||
if (stereo) {
|
||||
bytestream_put_byte(&out, (context->lastSample[1])>>8);
|
||||
bytestream_put_byte(&out, (context->lastSample[0])>>8);
|
||||
} else
|
||||
bytestream_put_le16(&out, context->lastSample[0]);
|
||||
|
||||
/* Write the actual samples */
|
||||
samples = avctx->frame_size;
|
||||
for (i=0; i<samples; i++)
|
||||
for (ch=0; ch<avctx->channels; ch++)
|
||||
*out++ = dpcm_predict(&context->lastSample[ch], *in++);
|
||||
|
||||
/* Use smaller frames from now on */
|
||||
avctx->frame_size = ROQ_FRAME_SIZE;
|
||||
|
||||
/* Return the result size */
|
||||
return out - frame;
|
||||
}
|
||||
|
||||
static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx)
|
||||
{
|
||||
av_freep(&avctx->coded_frame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVCodec roq_dpcm_encoder = {
|
||||
"roq_dpcm",
|
||||
CODEC_TYPE_AUDIO,
|
||||
CODEC_ID_ROQ_DPCM,
|
||||
sizeof(ROQDPCMContext_t),
|
||||
roq_dpcm_encode_init,
|
||||
roq_dpcm_encode_frame,
|
||||
roq_dpcm_encode_close,
|
||||
NULL,
|
||||
.sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
|
||||
.long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"),
|
||||
};
|
@ -1,501 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2003 the ffmpeg project
|
||||
* Copyright (C) 2003 Mike Melanson
|
||||
* Copyright (C) 2003 Dr. Tim Ferguson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file roqvideo.c
|
||||
* Id RoQ Video Decoder by Dr. Tim Ferguson
|
||||
* For more information about the Id RoQ format, visit:
|
||||
* http://www.csse.monash.edu.au/~timf/
|
||||
* id RoQ Video common functions based on work by Dr. Tim Ferguson
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "avcodec.h"
|
||||
#include "dsputil.h"
|
||||
#include "roqvideo.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char y0, y1, y2, y3, u, v;
|
||||
} roq_cell;
|
||||
|
||||
typedef struct {
|
||||
int idx[4];
|
||||
} roq_qcell;
|
||||
|
||||
static int uiclip[1024], *uiclp; /* clipping table */
|
||||
#define avg2(a,b) uiclp[(((int)(a)+(int)(b)+1)>>1)]
|
||||
#define avg4(a,b,c,d) uiclp[(((int)(a)+(int)(b)+(int)(c)+(int)(d)+2)>>2)]
|
||||
|
||||
typedef struct RoqContext {
|
||||
|
||||
AVCodecContext *avctx;
|
||||
DSPContext dsp;
|
||||
AVFrame last_frame;
|
||||
AVFrame current_frame;
|
||||
int first_frame;
|
||||
int y_stride;
|
||||
int c_stride;
|
||||
|
||||
roq_cell cells[256];
|
||||
roq_qcell qcells[256];
|
||||
|
||||
unsigned char *buf;
|
||||
int size;
|
||||
|
||||
} RoqContext;
|
||||
|
||||
#define RoQ_INFO 0x1001
|
||||
#define RoQ_QUAD_CODEBOOK 0x1002
|
||||
#define RoQ_QUAD_VQ 0x1011
|
||||
#define RoQ_SOUND_MONO 0x1020
|
||||
#define RoQ_SOUND_STEREO 0x1021
|
||||
|
||||
#define RoQ_ID_MOT 0x00
|
||||
#define RoQ_ID_FCC 0x01
|
||||
#define RoQ_ID_SLD 0x02
|
||||
#define RoQ_ID_CCC 0x03
|
||||
|
||||
#define get_byte(in_buffer) *(in_buffer++)
|
||||
#define get_word(in_buffer) ((unsigned short)(in_buffer += 2, \
|
||||
(in_buffer[-1] << 8 | in_buffer[-2])))
|
||||
#define get_long(in_buffer) ((unsigned long)(in_buffer += 4, \
|
||||
(in_buffer[-1] << 24 | in_buffer[-2] << 16 | in_buffer[-3] << 8 | in_buffer[-4])))
|
||||
|
||||
|
||||
static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
|
||||
static inline void block_copy(unsigned char *out, unsigned char *in,
|
||||
int outstride, int instride, int sz)
|
||||
{
|
||||
unsigned char *yptr;
|
||||
|
||||
yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
|
||||
*yptr++ = cell->y0;
|
||||
*yptr++ = cell->y1;
|
||||
yptr += (ri->y_stride - 2);
|
||||
*yptr++ = cell->y2;
|
||||
*yptr++ = cell->y3;
|
||||
ri->current_frame.data[1][(y/2) * (ri->c_stride) + x/2] = cell->u;
|
||||
ri->current_frame.data[2][(y/2) * (ri->c_stride) + x/2] = cell->v;
|
||||
int rows = sz;
|
||||
while(rows--) {
|
||||
memcpy(out, in, sz);
|
||||
out += outstride;
|
||||
in += instride;
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
|
||||
void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
|
||||
{
|
||||
unsigned long row_inc, c_row_inc;
|
||||
register unsigned char y0, y1, u, v;
|
||||
unsigned char *yptr, *uptr, *vptr;
|
||||
unsigned char *bptr;
|
||||
int boffs,stride;
|
||||
|
||||
yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
|
||||
uptr = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
|
||||
vptr = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
|
||||
stride = ri->current_frame->linesize[0];
|
||||
boffs = y*stride + x;
|
||||
|
||||
row_inc = ri->y_stride - 4;
|
||||
c_row_inc = (ri->c_stride) - 2;
|
||||
*yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
|
||||
*yptr++ = y0;
|
||||
*yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
|
||||
*yptr++ = y1;
|
||||
bptr = ri->current_frame->data[0] + boffs;
|
||||
bptr[0 ] = cell->y[0];
|
||||
bptr[1 ] = cell->y[1];
|
||||
bptr[stride ] = cell->y[2];
|
||||
bptr[stride+1] = cell->y[3];
|
||||
|
||||
yptr += row_inc;
|
||||
stride = ri->current_frame->linesize[1];
|
||||
boffs = y*stride + x;
|
||||
|
||||
*yptr++ = y0;
|
||||
*yptr++ = y0;
|
||||
*yptr++ = y1;
|
||||
*yptr++ = y1;
|
||||
bptr = ri->current_frame->data[1] + boffs;
|
||||
bptr[0 ] =
|
||||
bptr[1 ] =
|
||||
bptr[stride ] =
|
||||
bptr[stride+1] = cell->u;
|
||||
|
||||
yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
|
||||
|
||||
*yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
|
||||
*yptr++ = y0;
|
||||
*yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
|
||||
*yptr++ = y1;
|
||||
|
||||
yptr += row_inc;
|
||||
|
||||
*yptr++ = y0;
|
||||
*yptr++ = y0;
|
||||
*yptr++ = y1;
|
||||
*yptr++ = y1;
|
||||
bptr = ri->current_frame->data[2] + boffs;
|
||||
bptr[0 ] =
|
||||
bptr[1 ] =
|
||||
bptr[stride ] =
|
||||
bptr[stride+1] = cell->v;
|
||||
}
|
||||
|
||||
static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv,
|
||||
signed char mean_x, signed char mean_y)
|
||||
void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
|
||||
{
|
||||
int i, hw, mx, my;
|
||||
unsigned char *pa, *pb;
|
||||
unsigned char *bptr;
|
||||
int boffs,stride;
|
||||
|
||||
mx = x + 8 - (mv >> 4) - mean_x;
|
||||
my = y + 8 - (mv & 0xf) - mean_y;
|
||||
stride = ri->current_frame->linesize[0];
|
||||
boffs = y*stride + x;
|
||||
|
||||
pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
|
||||
pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
|
||||
for(i = 0; i < 4; i++) {
|
||||
pa[0] = pb[0];
|
||||
pa[1] = pb[1];
|
||||
pa[2] = pb[2];
|
||||
pa[3] = pb[3];
|
||||
pa += ri->y_stride;
|
||||
pb += ri->y_stride;
|
||||
}
|
||||
bptr = ri->current_frame->data[0] + boffs;
|
||||
bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = cell->y[0];
|
||||
bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = cell->y[1];
|
||||
bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = cell->y[2];
|
||||
bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->y[3];
|
||||
|
||||
#if 0
|
||||
pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
|
||||
pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2;
|
||||
for(i = 0; i < 2; i++) {
|
||||
pa[0] = pb[0];
|
||||
pa[1] = pb[1];
|
||||
pa += ri->c_stride;
|
||||
pb += ri->c_stride;
|
||||
}
|
||||
stride = ri->current_frame->linesize[1];
|
||||
boffs = y*stride + x;
|
||||
|
||||
pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
|
||||
pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2;
|
||||
for(i = 0; i < 2; i++) {
|
||||
pa[0] = pb[0];
|
||||
pa[1] = pb[1];
|
||||
pa += ri->c_stride;
|
||||
pb += ri->c_stride;
|
||||
}
|
||||
#else
|
||||
hw = ri->y_stride/2;
|
||||
pa = ri->current_frame.data[1] + (y * ri->y_stride)/4 + x/2;
|
||||
pb = ri->last_frame.data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
|
||||
bptr = ri->current_frame->data[1] + boffs;
|
||||
bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] =
|
||||
bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] =
|
||||
bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] =
|
||||
bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->u;
|
||||
|
||||
for(i = 0; i < 2; i++) {
|
||||
switch(((my & 0x01) << 1) | (mx & 0x01)) {
|
||||
|
||||
case 0:
|
||||
pa[0] = pb[0];
|
||||
pa[1] = pb[1];
|
||||
pa[hw] = pb[hw];
|
||||
pa[hw+1] = pb[hw+1];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
pa[0] = avg2(pb[0], pb[1]);
|
||||
pa[1] = avg2(pb[1], pb[2]);
|
||||
pa[hw] = avg2(pb[hw], pb[hw+1]);
|
||||
pa[hw+1] = avg2(pb[hw+1], pb[hw+2]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pa[0] = avg2(pb[0], pb[hw]);
|
||||
pa[1] = avg2(pb[1], pb[hw+1]);
|
||||
pa[hw] = avg2(pb[hw], pb[hw*2]);
|
||||
pa[hw+1] = avg2(pb[hw+1], pb[(hw*2)+1]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
|
||||
pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
|
||||
pa[hw] = avg4(pb[hw], pb[hw+1], pb[hw*2], pb[(hw*2)+1]);
|
||||
pa[hw+1] = avg4(pb[hw+1], pb[hw+2], pb[(hw*2)+1], pb[(hw*2)+1]);
|
||||
break;
|
||||
}
|
||||
|
||||
pa = ri->current_frame.data[2] + (y * ri->y_stride)/4 + x/2;
|
||||
pb = ri->last_frame.data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
|
||||
}
|
||||
#endif
|
||||
bptr = ri->current_frame->data[2] + boffs;
|
||||
bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] =
|
||||
bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] =
|
||||
bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] =
|
||||
bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->v;
|
||||
}
|
||||
|
||||
static void apply_motion_8x8(RoqContext *ri, int x, int y,
|
||||
unsigned char mv, signed char mean_x, signed char mean_y)
|
||||
|
||||
static inline void apply_motion_generic(RoqContext *ri, int x, int y, int deltax,
|
||||
int deltay, int sz)
|
||||
{
|
||||
int mx, my, i, j, hw;
|
||||
unsigned char *pa, *pb;
|
||||
int mx, my, cp;
|
||||
|
||||
mx = x + 8 - (mv >> 4) - mean_x;
|
||||
my = y + 8 - (mv & 0xf) - mean_y;
|
||||
mx = x + deltax;
|
||||
my = y + deltay;
|
||||
|
||||
pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
|
||||
pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
|
||||
for(i = 0; i < 8; i++) {
|
||||
pa[0] = pb[0];
|
||||
pa[1] = pb[1];
|
||||
pa[2] = pb[2];
|
||||
pa[3] = pb[3];
|
||||
pa[4] = pb[4];
|
||||
pa[5] = pb[5];
|
||||
pa[6] = pb[6];
|
||||
pa[7] = pb[7];
|
||||
pa += ri->y_stride;
|
||||
pb += ri->y_stride;
|
||||
/* check MV against frame boundaries */
|
||||
if ((mx < 0) || (mx > ri->width - sz) ||
|
||||
(my < 0) || (my > ri->height - sz)) {
|
||||
av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n",
|
||||
mx, my, ri->width, ri->height);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
|
||||
pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2;
|
||||
for(i = 0; i < 4; i++) {
|
||||
pa[0] = pb[0];
|
||||
pa[1] = pb[1];
|
||||
pa[2] = pb[2];
|
||||
pa[3] = pb[3];
|
||||
pa += ri->c_stride;
|
||||
pb += ri->c_stride;
|
||||
}
|
||||
|
||||
pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
|
||||
pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2;
|
||||
for(i = 0; i < 4; i++) {
|
||||
pa[0] = pb[0];
|
||||
pa[1] = pb[1];
|
||||
pa[2] = pb[2];
|
||||
pa[3] = pb[3];
|
||||
pa += ri->c_stride;
|
||||
pb += ri->c_stride;
|
||||
}
|
||||
#else
|
||||
hw = ri->c_stride;
|
||||
pa = ri->current_frame.data[1] + (y * ri->y_stride)/4 + x/2;
|
||||
pb = ri->last_frame.data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
|
||||
for(j = 0; j < 2; j++) {
|
||||
for(i = 0; i < 4; i++) {
|
||||
switch(((my & 0x01) << 1) | (mx & 0x01)) {
|
||||
|
||||
case 0:
|
||||
pa[0] = pb[0];
|
||||
pa[1] = pb[1];
|
||||
pa[2] = pb[2];
|
||||
pa[3] = pb[3];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
pa[0] = avg2(pb[0], pb[1]);
|
||||
pa[1] = avg2(pb[1], pb[2]);
|
||||
pa[2] = avg2(pb[2], pb[3]);
|
||||
pa[3] = avg2(pb[3], pb[4]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pa[0] = avg2(pb[0], pb[hw]);
|
||||
pa[1] = avg2(pb[1], pb[hw+1]);
|
||||
pa[2] = avg2(pb[2], pb[hw+2]);
|
||||
pa[3] = avg2(pb[3], pb[hw+3]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
|
||||
pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
|
||||
pa[2] = avg4(pb[2], pb[3], pb[hw+2], pb[hw+3]);
|
||||
pa[3] = avg4(pb[3], pb[4], pb[hw+3], pb[hw+4]);
|
||||
break;
|
||||
}
|
||||
pa += ri->c_stride;
|
||||
pb += ri->c_stride;
|
||||
}
|
||||
|
||||
pa = ri->current_frame.data[2] + (y * ri->y_stride)/4 + x/2;
|
||||
pb = ri->last_frame.data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void roqvideo_decode_frame(RoqContext *ri)
|
||||
{
|
||||
unsigned int chunk_id = 0, chunk_arg = 0;
|
||||
unsigned long chunk_size = 0;
|
||||
int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
|
||||
int vqid, bpos, xpos, ypos, xp, yp, x, y;
|
||||
int frame_stats[2][4] = {{0},{0}};
|
||||
roq_qcell *qcell;
|
||||
unsigned char *buf = ri->buf;
|
||||
unsigned char *buf_end = ri->buf + ri->size;
|
||||
|
||||
while (buf < buf_end) {
|
||||
chunk_id = get_word(buf);
|
||||
chunk_size = get_long(buf);
|
||||
chunk_arg = get_word(buf);
|
||||
|
||||
if(chunk_id == RoQ_QUAD_VQ)
|
||||
break;
|
||||
if(chunk_id == RoQ_QUAD_CODEBOOK) {
|
||||
if((nv1 = chunk_arg >> 8) == 0)
|
||||
nv1 = 256;
|
||||
if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
|
||||
nv2 = 256;
|
||||
for(i = 0; i < nv1; i++) {
|
||||
ri->cells[i].y0 = get_byte(buf);
|
||||
ri->cells[i].y1 = get_byte(buf);
|
||||
ri->cells[i].y2 = get_byte(buf);
|
||||
ri->cells[i].y3 = get_byte(buf);
|
||||
ri->cells[i].u = get_byte(buf);
|
||||
ri->cells[i].v = get_byte(buf);
|
||||
}
|
||||
for(i = 0; i < nv2; i++)
|
||||
for(j = 0; j < 4; j++)
|
||||
ri->qcells[i].idx[j] = get_byte(buf);
|
||||
}
|
||||
}
|
||||
|
||||
bpos = xpos = ypos = 0;
|
||||
while(bpos < chunk_size) {
|
||||
for (yp = ypos; yp < ypos + 16; yp += 8)
|
||||
for (xp = xpos; xp < xpos + 16; xp += 8) {
|
||||
if (vqflg_pos < 0) {
|
||||
vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
|
||||
vqflg_pos = 7;
|
||||
}
|
||||
vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
|
||||
frame_stats[0][vqid]++;
|
||||
vqflg_pos--;
|
||||
|
||||
switch(vqid) {
|
||||
case RoQ_ID_MOT:
|
||||
apply_motion_8x8(ri, xp, yp, 0, 8, 8);
|
||||
break;
|
||||
case RoQ_ID_FCC:
|
||||
apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8,
|
||||
chunk_arg & 0xff);
|
||||
break;
|
||||
case RoQ_ID_SLD:
|
||||
qcell = ri->qcells + buf[bpos++];
|
||||
apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]);
|
||||
apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]);
|
||||
apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]);
|
||||
apply_vector_4x4(ri, xp+4, yp+4, ri->cells + qcell->idx[3]);
|
||||
break;
|
||||
case RoQ_ID_CCC:
|
||||
for (k = 0; k < 4; k++) {
|
||||
x = xp; y = yp;
|
||||
if(k & 0x01) x += 4;
|
||||
if(k & 0x02) y += 4;
|
||||
|
||||
if (vqflg_pos < 0) {
|
||||
vqflg = buf[bpos++];
|
||||
vqflg |= (buf[bpos++] << 8);
|
||||
vqflg_pos = 7;
|
||||
}
|
||||
vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
|
||||
frame_stats[1][vqid]++;
|
||||
vqflg_pos--;
|
||||
switch(vqid) {
|
||||
case RoQ_ID_MOT:
|
||||
apply_motion_4x4(ri, x, y, 0, 8, 8);
|
||||
break;
|
||||
case RoQ_ID_FCC:
|
||||
apply_motion_4x4(ri, x, y, buf[bpos++],
|
||||
chunk_arg >> 8, chunk_arg & 0xff);
|
||||
break;
|
||||
case RoQ_ID_SLD:
|
||||
qcell = ri->qcells + buf[bpos++];
|
||||
apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]);
|
||||
apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]);
|
||||
apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]);
|
||||
apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]);
|
||||
break;
|
||||
case RoQ_ID_CCC:
|
||||
apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]);
|
||||
apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]);
|
||||
apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]);
|
||||
apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]);
|
||||
bpos += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid);
|
||||
}
|
||||
}
|
||||
|
||||
xpos += 16;
|
||||
if (xpos >= ri->avctx->width) {
|
||||
xpos -= ri->avctx->width;
|
||||
ypos += 16;
|
||||
}
|
||||
if(ypos >= ri->avctx->height)
|
||||
break;
|
||||
for(cp = 0; cp < 3; cp++) {
|
||||
int outstride = ri->current_frame->linesize[cp];
|
||||
int instride = ri->last_frame ->linesize[cp];
|
||||
block_copy(ri->current_frame->data[cp] + y*outstride + x,
|
||||
ri->last_frame->data[cp] + my*instride + mx,
|
||||
outstride, instride, sz);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int roq_decode_init(AVCodecContext *avctx)
|
||||
void ff_apply_motion_4x4(RoqContext *ri, int x, int y,
|
||||
int deltax, int deltay)
|
||||
{
|
||||
RoqContext *s = avctx->priv_data;
|
||||
int i;
|
||||
|
||||
s->avctx = avctx;
|
||||
s->first_frame = 1;
|
||||
avctx->pix_fmt = PIX_FMT_YUV420P;
|
||||
avctx->has_b_frames = 0;
|
||||
dsputil_init(&s->dsp, avctx);
|
||||
|
||||
uiclp = uiclip+512;
|
||||
for(i = -512; i < 512; i++)
|
||||
uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i));
|
||||
|
||||
return 0;
|
||||
apply_motion_generic(ri, x, y, deltax, deltay, 4);
|
||||
}
|
||||
|
||||
static int roq_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
uint8_t *buf, int buf_size)
|
||||
void ff_apply_motion_8x8(RoqContext *ri, int x, int y,
|
||||
int deltax, int deltay)
|
||||
{
|
||||
RoqContext *s = avctx->priv_data;
|
||||
|
||||
*data_size = 0;
|
||||
|
||||
if (avctx->get_buffer(avctx, &s->current_frame)) {
|
||||
av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
s->y_stride = s->current_frame.linesize[0];
|
||||
s->c_stride = s->current_frame.linesize[1];
|
||||
|
||||
s->buf = buf;
|
||||
s->size = buf_size;
|
||||
roqvideo_decode_frame(s);
|
||||
|
||||
/* release the last frame if it is allocated */
|
||||
if (s->first_frame)
|
||||
s->first_frame = 0;
|
||||
else
|
||||
avctx->release_buffer(avctx, &s->last_frame);
|
||||
|
||||
/* shuffle frames */
|
||||
s->last_frame = s->current_frame;
|
||||
|
||||
*data_size = sizeof(AVFrame);
|
||||
*(AVFrame*)data = s->current_frame;
|
||||
|
||||
return buf_size;
|
||||
apply_motion_generic(ri, x, y, deltax, deltay, 8);
|
||||
}
|
||||
|
||||
static int roq_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
RoqContext *s = avctx->priv_data;
|
||||
|
||||
/* release the last frame */
|
||||
avctx->release_buffer(avctx, &s->last_frame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVCodec roq_decoder = {
|
||||
"roqvideo",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_ROQ,
|
||||
sizeof(RoqContext),
|
||||
roq_decode_init,
|
||||
NULL,
|
||||
roq_decode_end,
|
||||
roq_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
};
|
||||
|
92
src/add-ons/media/plugins/avcodec/libavcodec/roqvideo.h
Normal file
92
src/add-ons/media/plugins/avcodec/libavcodec/roqvideo.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Mike Melanson
|
||||
* Copyright (C) 2003 Dr. Tim Ferguson
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_ROQVIDEO_H
|
||||
#define FFMPEG_ROQVIDEO_H
|
||||
|
||||
#include "libavutil/random.h"
|
||||
#include "avcodec.h"
|
||||
#include "dsputil.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char y[4];
|
||||
unsigned char u, v;
|
||||
} roq_cell;
|
||||
|
||||
typedef struct {
|
||||
int idx[4];
|
||||
} roq_qcell;
|
||||
|
||||
typedef struct {
|
||||
int d[2];
|
||||
} motion_vect;
|
||||
|
||||
typedef struct RoqContext {
|
||||
|
||||
AVCodecContext *avctx;
|
||||
DSPContext dsp;
|
||||
AVFrame frames[2];
|
||||
AVFrame *last_frame;
|
||||
AVFrame *current_frame;
|
||||
int first_frame;
|
||||
|
||||
roq_cell cb2x2[256];
|
||||
roq_qcell cb4x4[256];
|
||||
|
||||
const unsigned char *buf;
|
||||
int size;
|
||||
int width, height;
|
||||
|
||||
/* Encoder only data */
|
||||
AVRandomState randctx;
|
||||
uint64_t lambda;
|
||||
|
||||
motion_vect *this_motion4;
|
||||
motion_vect *last_motion4;
|
||||
|
||||
motion_vect *this_motion8;
|
||||
motion_vect *last_motion8;
|
||||
|
||||
unsigned int framesSinceKeyframe;
|
||||
|
||||
AVFrame *frame_to_enc;
|
||||
uint8_t *out_buf;
|
||||
} RoqContext;
|
||||
|
||||
#define RoQ_INFO 0x1001
|
||||
#define RoQ_QUAD_CODEBOOK 0x1002
|
||||
#define RoQ_QUAD_VQ 0x1011
|
||||
#define RoQ_SOUND_MONO 0x1020
|
||||
#define RoQ_SOUND_STEREO 0x1021
|
||||
|
||||
#define RoQ_ID_MOT 0x00
|
||||
#define RoQ_ID_FCC 0x01
|
||||
#define RoQ_ID_SLD 0x02
|
||||
#define RoQ_ID_CCC 0x03
|
||||
|
||||
void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell);
|
||||
void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell);
|
||||
|
||||
void ff_apply_motion_4x4(RoqContext *ri, int x, int y, int deltax, int deltay);
|
||||
|
||||
void ff_apply_motion_8x8(RoqContext *ri, int x, int y, int deltax, int deltay);
|
||||
|
||||
#endif /* FFMPEG_ROQVIDEO_H */
|
223
src/add-ons/media/plugins/avcodec/libavcodec/roqvideodec.c
Normal file
223
src/add-ons/media/plugins/avcodec/libavcodec/roqvideodec.c
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (C) 2003 the ffmpeg project
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file roqvideodec.c
|
||||
* id RoQ Video Decoder by Dr. Tim Ferguson
|
||||
* For more information about the id RoQ format, visit:
|
||||
* http://www.csse.monash.edu.au/~timf/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "roqvideo.h"
|
||||
|
||||
static void roqvideo_decode_frame(RoqContext *ri)
|
||||
{
|
||||
unsigned int chunk_id = 0, chunk_arg = 0;
|
||||
unsigned long chunk_size = 0;
|
||||
int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
|
||||
int vqid, bpos, xpos, ypos, xp, yp, x, y, mx, my;
|
||||
int frame_stats[2][4] = {{0},{0}};
|
||||
roq_qcell *qcell;
|
||||
const unsigned char *buf = ri->buf;
|
||||
const unsigned char *buf_end = ri->buf + ri->size;
|
||||
|
||||
while (buf < buf_end) {
|
||||
chunk_id = bytestream_get_le16(&buf);
|
||||
chunk_size = bytestream_get_le32(&buf);
|
||||
chunk_arg = bytestream_get_le16(&buf);
|
||||
|
||||
if(chunk_id == RoQ_QUAD_VQ)
|
||||
break;
|
||||
if(chunk_id == RoQ_QUAD_CODEBOOK) {
|
||||
if((nv1 = chunk_arg >> 8) == 0)
|
||||
nv1 = 256;
|
||||
if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
|
||||
nv2 = 256;
|
||||
for(i = 0; i < nv1; i++) {
|
||||
ri->cb2x2[i].y[0] = *buf++;
|
||||
ri->cb2x2[i].y[1] = *buf++;
|
||||
ri->cb2x2[i].y[2] = *buf++;
|
||||
ri->cb2x2[i].y[3] = *buf++;
|
||||
ri->cb2x2[i].u = *buf++;
|
||||
ri->cb2x2[i].v = *buf++;
|
||||
}
|
||||
for(i = 0; i < nv2; i++)
|
||||
for(j = 0; j < 4; j++)
|
||||
ri->cb4x4[i].idx[j] = *buf++;
|
||||
}
|
||||
}
|
||||
|
||||
bpos = xpos = ypos = 0;
|
||||
while(bpos < chunk_size) {
|
||||
for (yp = ypos; yp < ypos + 16; yp += 8)
|
||||
for (xp = xpos; xp < xpos + 16; xp += 8) {
|
||||
if (vqflg_pos < 0) {
|
||||
vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
|
||||
vqflg_pos = 7;
|
||||
}
|
||||
vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
|
||||
frame_stats[0][vqid]++;
|
||||
vqflg_pos--;
|
||||
|
||||
switch(vqid) {
|
||||
case RoQ_ID_MOT:
|
||||
break;
|
||||
case RoQ_ID_FCC:
|
||||
mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8));
|
||||
my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg);
|
||||
ff_apply_motion_8x8(ri, xp, yp, mx, my);
|
||||
break;
|
||||
case RoQ_ID_SLD:
|
||||
qcell = ri->cb4x4 + buf[bpos++];
|
||||
ff_apply_vector_4x4(ri, xp, yp, ri->cb2x2 + qcell->idx[0]);
|
||||
ff_apply_vector_4x4(ri, xp+4, yp, ri->cb2x2 + qcell->idx[1]);
|
||||
ff_apply_vector_4x4(ri, xp, yp+4, ri->cb2x2 + qcell->idx[2]);
|
||||
ff_apply_vector_4x4(ri, xp+4, yp+4, ri->cb2x2 + qcell->idx[3]);
|
||||
break;
|
||||
case RoQ_ID_CCC:
|
||||
for (k = 0; k < 4; k++) {
|
||||
x = xp; y = yp;
|
||||
if(k & 0x01) x += 4;
|
||||
if(k & 0x02) y += 4;
|
||||
|
||||
if (vqflg_pos < 0) {
|
||||
vqflg = buf[bpos++];
|
||||
vqflg |= (buf[bpos++] << 8);
|
||||
vqflg_pos = 7;
|
||||
}
|
||||
vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
|
||||
frame_stats[1][vqid]++;
|
||||
vqflg_pos--;
|
||||
switch(vqid) {
|
||||
case RoQ_ID_MOT:
|
||||
break;
|
||||
case RoQ_ID_FCC:
|
||||
mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8));
|
||||
my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg);
|
||||
ff_apply_motion_4x4(ri, x, y, mx, my);
|
||||
break;
|
||||
case RoQ_ID_SLD:
|
||||
qcell = ri->cb4x4 + buf[bpos++];
|
||||
ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + qcell->idx[0]);
|
||||
ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + qcell->idx[1]);
|
||||
ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + qcell->idx[2]);
|
||||
ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + qcell->idx[3]);
|
||||
break;
|
||||
case RoQ_ID_CCC:
|
||||
ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + buf[bpos]);
|
||||
ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + buf[bpos+1]);
|
||||
ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + buf[bpos+2]);
|
||||
ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + buf[bpos+3]);
|
||||
bpos += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid);
|
||||
}
|
||||
}
|
||||
|
||||
xpos += 16;
|
||||
if (xpos >= ri->width) {
|
||||
xpos -= ri->width;
|
||||
ypos += 16;
|
||||
}
|
||||
if(ypos >= ri->height)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static av_cold int roq_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
RoqContext *s = avctx->priv_data;
|
||||
|
||||
s->avctx = avctx;
|
||||
s->width = avctx->width;
|
||||
s->height = avctx->height;
|
||||
s->last_frame = &s->frames[0];
|
||||
s->current_frame = &s->frames[1];
|
||||
avctx->pix_fmt = PIX_FMT_YUV444P;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int roq_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
RoqContext *s = avctx->priv_data;
|
||||
int copy= !s->current_frame->data[0];
|
||||
|
||||
if (avctx->reget_buffer(avctx, s->current_frame)) {
|
||||
av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(copy)
|
||||
av_picture_copy((AVPicture*)s->current_frame, (AVPicture*)s->last_frame,
|
||||
avctx->pix_fmt, avctx->width, avctx->height);
|
||||
|
||||
s->buf = buf;
|
||||
s->size = buf_size;
|
||||
roqvideo_decode_frame(s);
|
||||
|
||||
*data_size = sizeof(AVFrame);
|
||||
*(AVFrame*)data = *s->current_frame;
|
||||
|
||||
/* shuffle frames */
|
||||
FFSWAP(AVFrame *, s->current_frame, s->last_frame);
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static av_cold int roq_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
RoqContext *s = avctx->priv_data;
|
||||
|
||||
/* release the last frame */
|
||||
if (s->last_frame->data[0])
|
||||
avctx->release_buffer(avctx, s->last_frame);
|
||||
if (s->current_frame->data[0])
|
||||
avctx->release_buffer(avctx, s->current_frame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVCodec roq_decoder = {
|
||||
"roqvideo",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_ROQ,
|
||||
sizeof(RoqContext),
|
||||
roq_decode_init,
|
||||
NULL,
|
||||
roq_decode_end,
|
||||
roq_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("id RoQ video"),
|
||||
};
|
1072
src/add-ons/media/plugins/avcodec/libavcodec/roqvideoenc.c
Normal file
1072
src/add-ons/media/plugins/avcodec/libavcodec/roqvideoenc.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,25 +2,26 @@
|
||||
* Quicktime Video (RPZA) Video Decoder
|
||||
* Copyright (C) 2003 the ffmpeg project
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file rpza.c
|
||||
* QT RPZA Video Decoder by Roberto Togni <rtogni@bresciaonline.it>
|
||||
* QT RPZA Video Decoder by Roberto Togni
|
||||
* For more information about the RPZA format, visit:
|
||||
* http://www.pcisys.net/~melanson/codecs/
|
||||
*
|
||||
@ -38,27 +39,18 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "avcodec.h"
|
||||
#include "dsputil.h"
|
||||
|
||||
typedef struct RpzaContext {
|
||||
|
||||
AVCodecContext *avctx;
|
||||
DSPContext dsp;
|
||||
AVFrame frame;
|
||||
|
||||
unsigned char *buf;
|
||||
const unsigned char *buf;
|
||||
int size;
|
||||
|
||||
} RpzaContext;
|
||||
|
||||
#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
|
||||
#define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
|
||||
(((uint8_t*)(x))[1] << 16) | \
|
||||
(((uint8_t*)(x))[2] << 8) | \
|
||||
((uint8_t*)(x))[3])
|
||||
|
||||
#define ADVANCE_BLOCK() \
|
||||
{ \
|
||||
pixel_ptr += 4; \
|
||||
@ -98,11 +90,11 @@ static void rpza_decode_stream(RpzaContext *s)
|
||||
|
||||
/* First byte is always 0xe1. Warn if it's different */
|
||||
if (s->buf[stream_ptr] != 0xe1)
|
||||
av_log(s->avctx, AV_LOG_ERROR, "First chunk byte is 0x%02x instead of 0x1e\n",
|
||||
av_log(s->avctx, AV_LOG_ERROR, "First chunk byte is 0x%02x instead of 0xe1\n",
|
||||
s->buf[stream_ptr]);
|
||||
|
||||
/* Get chunk size, ingnoring first byte */
|
||||
chunk_size = BE_32(&s->buf[stream_ptr]) & 0x00FFFFFF;
|
||||
chunk_size = AV_RB32(&s->buf[stream_ptr]) & 0x00FFFFFF;
|
||||
stream_ptr += 4;
|
||||
|
||||
/* If length mismatch use size from MOV file and try to decode anyway */
|
||||
@ -112,7 +104,7 @@ static void rpza_decode_stream(RpzaContext *s)
|
||||
chunk_size = s->size;
|
||||
|
||||
/* Number of 4x4 blocks in frame. */
|
||||
total_blocks = (s->avctx->width * s->avctx->height) / (4 * 4);
|
||||
total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
|
||||
|
||||
/* Process chunk data */
|
||||
while (stream_ptr < chunk_size) {
|
||||
@ -125,8 +117,8 @@ static void rpza_decode_stream(RpzaContext *s)
|
||||
colorA = (opcode << 8) | (s->buf[stream_ptr++]);
|
||||
opcode = 0;
|
||||
if ((s->buf[stream_ptr] & 0x80) != 0) {
|
||||
/* Must behave as opcode 110xxxxx, using colorA computed
|
||||
* above. Use fake opcode 0x20 to enter switch block at
|
||||
/* Must behave as opcode 110xxxxx, using colorA computed
|
||||
* above. Use fake opcode 0x20 to enter switch block at
|
||||
* the right place */
|
||||
opcode = 0x20;
|
||||
n_blocks = 1;
|
||||
@ -144,7 +136,7 @@ static void rpza_decode_stream(RpzaContext *s)
|
||||
|
||||
/* Fill blocks with one color */
|
||||
case 0xa0:
|
||||
colorA = BE_16 (&s->buf[stream_ptr]);
|
||||
colorA = AV_RB16 (&s->buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
while (n_blocks--) {
|
||||
block_ptr = row_ptr + pixel_ptr;
|
||||
@ -161,10 +153,10 @@ static void rpza_decode_stream(RpzaContext *s)
|
||||
|
||||
/* Fill blocks with 4 colors */
|
||||
case 0xc0:
|
||||
colorA = BE_16 (&s->buf[stream_ptr]);
|
||||
colorA = AV_RB16 (&s->buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
case 0x20:
|
||||
colorB = BE_16 (&s->buf[stream_ptr]);
|
||||
colorB = AV_RB16 (&s->buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
|
||||
/* sort out the colors */
|
||||
@ -213,7 +205,7 @@ static void rpza_decode_stream(RpzaContext *s)
|
||||
for (pixel_x = 0; pixel_x < 4; pixel_x++){
|
||||
/* We already have color of upper left pixel */
|
||||
if ((pixel_y != 0) || (pixel_x !=0)) {
|
||||
colorA = BE_16 (&s->buf[stream_ptr]);
|
||||
colorA = AV_RB16 (&s->buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
}
|
||||
pixels[block_ptr] = colorA;
|
||||
@ -234,14 +226,12 @@ static void rpza_decode_stream(RpzaContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
static int rpza_decode_init(AVCodecContext *avctx)
|
||||
static av_cold int rpza_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
RpzaContext *s = (RpzaContext *)avctx->priv_data;
|
||||
RpzaContext *s = avctx->priv_data;
|
||||
|
||||
s->avctx = avctx;
|
||||
avctx->pix_fmt = PIX_FMT_RGB555;
|
||||
avctx->has_b_frames = 0;
|
||||
dsputil_init(&s->dsp, avctx);
|
||||
|
||||
s->frame.data[0] = NULL;
|
||||
|
||||
@ -250,13 +240,9 @@ static int rpza_decode_init(AVCodecContext *avctx)
|
||||
|
||||
static int rpza_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
uint8_t *buf, int buf_size)
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
RpzaContext *s = (RpzaContext *)avctx->priv_data;
|
||||
|
||||
/* no supplementary picture */
|
||||
if (buf_size == 0)
|
||||
return 0;
|
||||
RpzaContext *s = avctx->priv_data;
|
||||
|
||||
s->buf = buf;
|
||||
s->size = buf_size;
|
||||
@ -277,9 +263,9 @@ static int rpza_decode_frame(AVCodecContext *avctx,
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static int rpza_decode_end(AVCodecContext *avctx)
|
||||
static av_cold int rpza_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
RpzaContext *s = (RpzaContext *)avctx->priv_data;
|
||||
RpzaContext *s = avctx->priv_data;
|
||||
|
||||
if (s->frame.data[0])
|
||||
avctx->release_buffer(avctx, &s->frame);
|
||||
@ -297,4 +283,5 @@ AVCodec rpza_decoder = {
|
||||
rpza_decode_end,
|
||||
rpza_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"),
|
||||
};
|
||||
|
165
src/add-ons/media/plugins/avcodec/libavcodec/rtjpeg.c
Normal file
165
src/add-ons/media/plugins/avcodec/libavcodec/rtjpeg.c
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* RTJpeg decoding functions
|
||||
* Copyright (c) 2006 Reimar Doeffinger
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "bitstream.h"
|
||||
#include "dsputil.h"
|
||||
#include "rtjpeg.h"
|
||||
|
||||
#define PUT_COEFF(c) \
|
||||
i = scan[coeff--]; \
|
||||
block[i] = (c) * quant[i];
|
||||
|
||||
//! aligns the bitstream to the give power of two
|
||||
#define ALIGN(a) \
|
||||
n = (-get_bits_count(gb)) & (a - 1); \
|
||||
if (n) {skip_bits(gb, n);}
|
||||
|
||||
/**
|
||||
* \brief read one block from stream
|
||||
* \param gb contains stream data
|
||||
* \param block where data is written to
|
||||
* \param scan array containing the mapping stream address -> block position
|
||||
* \param quant quantization factors
|
||||
*
|
||||
* Note: GetBitContext is used to make the code simpler, since all data is
|
||||
* aligned this could be done faster in a different way, e.g. as it is done
|
||||
* in MPlayer libmpcodecs/native/rtjpegn.c.
|
||||
*/
|
||||
static inline int get_block(GetBitContext *gb, DCTELEM *block, const uint8_t *scan,
|
||||
const uint32_t *quant) {
|
||||
int coeff, i, n;
|
||||
int8_t ac;
|
||||
uint8_t dc = get_bits(gb, 8);
|
||||
|
||||
// block not coded
|
||||
if (dc == 255)
|
||||
return 0;
|
||||
|
||||
// number of non-zero coefficients
|
||||
coeff = get_bits(gb, 6);
|
||||
// normally we would only need to clear the (63 - coeff) last values,
|
||||
// but since we do not know where they are we just clear the whole block
|
||||
memset(block, 0, 64 * sizeof(DCTELEM));
|
||||
|
||||
// 2 bits per coefficient
|
||||
while (coeff) {
|
||||
ac = get_sbits(gb, 2);
|
||||
if (ac == -2)
|
||||
break; // continue with more bits
|
||||
PUT_COEFF(ac);
|
||||
}
|
||||
|
||||
// 4 bits per coefficient
|
||||
ALIGN(4);
|
||||
while (coeff) {
|
||||
ac = get_sbits(gb, 4);
|
||||
if (ac == -8)
|
||||
break; // continue with more bits
|
||||
PUT_COEFF(ac);
|
||||
}
|
||||
|
||||
// 8 bits per coefficient
|
||||
ALIGN(8);
|
||||
while (coeff) {
|
||||
ac = get_sbits(gb, 8);
|
||||
PUT_COEFF(ac);
|
||||
}
|
||||
|
||||
PUT_COEFF(dc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief decode one rtjpeg YUV420 frame
|
||||
* \param c context, must be initialized via rtjpeg_decode_init
|
||||
* \param f AVFrame to place decoded frame into. If parts of the frame
|
||||
* are not coded they are left unchanged, so consider initializing it
|
||||
* \param buf buffer containing input data
|
||||
* \param buf_size length of input data in bytes
|
||||
* \return number of bytes consumed from the input buffer
|
||||
*/
|
||||
int rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f,
|
||||
const uint8_t *buf, int buf_size) {
|
||||
DECLARE_ALIGNED_16(DCTELEM, block[64]);
|
||||
GetBitContext gb;
|
||||
int w = c->w / 16, h = c->h / 16;
|
||||
int x, y;
|
||||
uint8_t *y1 = f->data[0], *y2 = f->data[0] + 8 * f->linesize[0];
|
||||
uint8_t *u = f->data[1], *v = f->data[2];
|
||||
init_get_bits(&gb, buf, buf_size * 8);
|
||||
for (y = 0; y < h; y++) {
|
||||
for (x = 0; x < w; x++) {
|
||||
if (get_block(&gb, block, c->scan, c->lquant))
|
||||
c->dsp->idct_put(y1, f->linesize[0], block);
|
||||
y1 += 8;
|
||||
if (get_block(&gb, block, c->scan, c->lquant))
|
||||
c->dsp->idct_put(y1, f->linesize[0], block);
|
||||
y1 += 8;
|
||||
if (get_block(&gb, block, c->scan, c->lquant))
|
||||
c->dsp->idct_put(y2, f->linesize[0], block);
|
||||
y2 += 8;
|
||||
if (get_block(&gb, block, c->scan, c->lquant))
|
||||
c->dsp->idct_put(y2, f->linesize[0], block);
|
||||
y2 += 8;
|
||||
if (get_block(&gb, block, c->scan, c->cquant))
|
||||
c->dsp->idct_put(u, f->linesize[1], block);
|
||||
u += 8;
|
||||
if (get_block(&gb, block, c->scan, c->cquant))
|
||||
c->dsp->idct_put(v, f->linesize[2], block);
|
||||
v += 8;
|
||||
}
|
||||
y1 += 2 * 8 * (f->linesize[0] - w);
|
||||
y2 += 2 * 8 * (f->linesize[0] - w);
|
||||
u += 8 * (f->linesize[1] - w);
|
||||
v += 8 * (f->linesize[2] - w);
|
||||
}
|
||||
return get_bits_count(&gb) / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief initialize an RTJpegContext, may be called multiple times
|
||||
* \param c context to initialize
|
||||
* \param dsp specifies the idct to use for decoding
|
||||
* \param width width of image, will be rounded down to the nearest multiple
|
||||
* of 16 for decoding
|
||||
* \param height height of image, will be rounded down to the nearest multiple
|
||||
* of 16 for decoding
|
||||
* \param lquant luma quantization table to use
|
||||
* \param cquant chroma quantization table to use
|
||||
*/
|
||||
void rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp,
|
||||
int width, int height,
|
||||
const uint32_t *lquant, const uint32_t *cquant) {
|
||||
int i;
|
||||
c->dsp = dsp;
|
||||
for (i = 0; i < 64; i++) {
|
||||
int z = ff_zigzag_direct[i];
|
||||
int p = c->dsp->idct_permutation[i];
|
||||
z = ((z << 3) | (z >> 3)) & 63; // rtjpeg uses a transposed variant
|
||||
|
||||
// permute the scan and quantization tables for the chosen idct
|
||||
c->scan[i] = c->dsp->idct_permutation[z];
|
||||
c->lquant[p] = lquant[i];
|
||||
c->cquant[p] = cquant[i];
|
||||
}
|
||||
c->w = width;
|
||||
c->h = height;
|
||||
}
|
42
src/add-ons/media/plugins/avcodec/libavcodec/rtjpeg.h
Normal file
42
src/add-ons/media/plugins/avcodec/libavcodec/rtjpeg.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* RTJpeg decoding functions
|
||||
* copyright (c) 2006 Reimar Doeffinger
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_RTJPEG_H
|
||||
#define FFMPEG_RTJPEG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "dsputil.h"
|
||||
|
||||
typedef struct {
|
||||
int w, h;
|
||||
DSPContext *dsp;
|
||||
uint8_t scan[64];
|
||||
uint32_t lquant[64];
|
||||
uint32_t cquant[64];
|
||||
} RTJpegContext;
|
||||
|
||||
void rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp,
|
||||
int width, int height,
|
||||
const uint32_t *lquant, const uint32_t *cquant);
|
||||
|
||||
int rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f,
|
||||
const uint8_t *buf, int buf_size);
|
||||
#endif /* FFMPEG_RTJPEG_H */
|
Loading…
x
Reference in New Issue
Block a user