Update avcodec to 20080825

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27557 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2008-09-15 14:09:46 +00:00
parent 65509a25cd
commit 2aa0a78774
33 changed files with 9940 additions and 6156 deletions
@@ -2,26 +2,28 @@
* MACE decoder
* Copyright (c) 2002 Laszlo Torok <[email protected]>
*
* 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 mace.c
* MACE decoder.
*/
#include "avcodec.h"
/*
@@ -242,7 +244,8 @@ typedef struct MACEContext {
static void chomp3(MACEContext *ctx,
uint8_t val,
const uint16_t tab1[],
const uint16_t tab2[][8])
const uint16_t tab2[][8],
uint32_t numChannels)
{
short current;
@@ -252,14 +255,15 @@ static void chomp3(MACEContext *ctx,
else current+=ctx->lev;
ctx->lev=current-(current >> 3);
// *ctx->outPtr++=current >> 8;
*ctx->outPtr++=current;
*ctx->outPtr=current;
ctx->outPtr+=numChannels;
if ( ( ctx->index += tab1[val]-(ctx->index>>5) ) < 0 ) ctx->index = 0;
}
/* \\\ */
/* /// "Exp1to3()" */
static void Exp1to3(MACEContext *ctx,
uint8_t *inBuffer,
const uint8_t *inBuffer,
void *outBuffer,
uint32_t cnt,
uint32_t numChannels,
@@ -281,13 +285,13 @@ static void Exp1to3(MACEContext *ctx,
while (cnt>0) {
pkt=inBuffer[0];
chomp3(ctx, pkt & 7, MACEtab1, MACEtab2);
chomp3(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4);
chomp3(ctx, pkt >> 5 , MACEtab1, MACEtab2);
chomp3(ctx, pkt & 7, MACEtab1, MACEtab2, numChannels);
chomp3(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4, numChannels);
chomp3(ctx, pkt >> 5 , MACEtab1, MACEtab2, numChannels);
pkt=inBuffer[1];
chomp3(ctx, pkt & 7, MACEtab1, MACEtab2);
chomp3(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4);
chomp3(ctx, pkt >> 5 , MACEtab1, MACEtab2);
chomp3(ctx, pkt & 7, MACEtab1, MACEtab2, numChannels);
chomp3(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4, numChannels);
chomp3(ctx, pkt >> 5 , MACEtab1, MACEtab2, numChannels);
inBuffer+=numChannels*2;
--cnt;
@@ -306,7 +310,8 @@ static void Exp1to3(MACEContext *ctx,
static void chomp6(MACEContext *ctx,
uint8_t val,
const uint16_t tab1[],
const uint16_t tab2[][8])
const uint16_t tab2[][8],
uint32_t numChannels)
{
short current;
@@ -329,9 +334,10 @@ static void chomp6(MACEContext *ctx,
// *ctx->outPtr++=(ctx->previous+ctx->prev2-((ctx->prev2-current) >> 2)) >> 8;
// *ctx->outPtr++=(ctx->previous+current+((ctx->prev2-current) >> 2)) >> 8;
*ctx->outPtr++=(ctx->previous+ctx->prev2-((ctx->prev2-current) >> 2));
*ctx->outPtr++=(ctx->previous+current+((ctx->prev2-current) >> 2));
*ctx->outPtr=(ctx->previous+ctx->prev2-((ctx->prev2-current) >> 2));
ctx->outPtr+=numChannels;
*ctx->outPtr=(ctx->previous+current+((ctx->prev2-current) >> 2));
ctx->outPtr+=numChannels;
ctx->prev2=ctx->previous;
ctx->previous=current;
@@ -341,7 +347,7 @@ static void chomp6(MACEContext *ctx,
/* /// "Exp1to6()" */
static void Exp1to6(MACEContext *ctx,
uint8_t *inBuffer,
const uint8_t *inBuffer,
void *outBuffer,
uint32_t cnt,
uint32_t numChannels,
@@ -366,9 +372,9 @@ static void Exp1to6(MACEContext *ctx,
while (cnt>0) {
pkt=*inBuffer;
chomp6(ctx, pkt >> 5 , MACEtab1, MACEtab2);
chomp6(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4);
chomp6(ctx, pkt & 7, MACEtab1, MACEtab2);
chomp6(ctx, pkt >> 5 , MACEtab1, MACEtab2, numChannels);
chomp6(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4, numChannels);
chomp6(ctx, pkt & 7, MACEtab1, MACEtab2, numChannels);
inBuffer+=numChannels;
--cnt;
@@ -386,16 +392,17 @@ static void Exp1to6(MACEContext *ctx,
}
/* \\\ */
static int mace_decode_init(AVCodecContext * avctx)
static av_cold int mace_decode_init(AVCodecContext * avctx)
{
if (avctx->channels > 2)
return -1;
avctx->sample_fmt = SAMPLE_FMT_S16;
return 0;
}
static int mace_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
const uint8_t *buf, int buf_size)
{
short *samples;
MACEContext *c = avctx->priv_data;
@@ -403,25 +410,20 @@ static int mace_decode_frame(AVCodecContext *avctx,
samples = (short *)data;
switch (avctx->codec->id) {
case CODEC_ID_MACE3:
#ifdef DEBUG
puts("mace_decode_frame[3]()");
#endif
Exp1to3(c, buf, samples, buf_size / 2, avctx->channels, 1);
dprintf(avctx, "mace_decode_frame[3]()");
Exp1to3(c, buf, samples, buf_size / 2 / avctx->channels, avctx->channels, 1);
if (avctx->channels == 2)
Exp1to3(c, buf, samples+1, buf_size / 2, 2, 2);
Exp1to3(c, buf, samples+1, buf_size / 2 / 2, 2, 2);
*data_size = 2 * 3 * buf_size;
break;
case CODEC_ID_MACE6:
#ifdef DEBUG
puts("mace_decode_frame[6]()");
#endif
Exp1to6(c, buf, samples, buf_size, avctx->channels, 1);
dprintf(avctx, "mace_decode_frame[6]()");
Exp1to6(c, buf, samples, buf_size / avctx->channels, avctx->channels, 1);
if (avctx->channels == 2)
Exp1to6(c, buf, samples+1, buf_size, 2, 2);
Exp1to6(c, buf, samples+1, buf_size / 2, 2, 2);
*data_size = 2 * 6 * buf_size;
break;
default:
*data_size = 0;
return -1;
}
return buf_size;
@@ -436,6 +438,7 @@ AVCodec mace3_decoder = {
NULL,
NULL,
mace_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 3:1"),
};
AVCodec mace6_decoder = {
@@ -447,5 +450,6 @@ AVCodec mace6_decoder = {
NULL,
NULL,
mace_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 6:1"),
};
@@ -0,0 +1,87 @@
/*
* simple math operations
* Copyright (c) 2001, 2002 Fabrice Bellard.
* Copyright (c) 2006 Michael Niedermayer <[email protected]> et al
*
* 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_MATHOPS_H
#define FFMPEG_MATHOPS_H
#include "common.h"
#ifdef ARCH_X86_32
#include "i386/mathops.h"
#elif defined(ARCH_ARMV4L)
#include "armv4l/mathops.h"
#elif defined(ARCH_POWERPC)
#include "ppc/mathops.h"
#elif defined(ARCH_BFIN)
#include "bfin/mathops.h"
#endif
/* generic implementation */
#ifndef MULL
# define MULL(a,b) (((int64_t)(a) * (int64_t)(b)) >> FRAC_BITS)
#endif
#ifndef MULH
//gcc 3.4 creates an incredibly bloated mess out of this
//# define MULH(a,b) (((int64_t)(a) * (int64_t)(b))>>32)
static av_always_inline int MULH(int a, int b){
return ((int64_t)(a) * (int64_t)(b))>>32;
}
#endif
#ifndef MUL64
# define MUL64(a,b) ((int64_t)(a) * (int64_t)(b))
#endif
#ifndef MAC64
# define MAC64(d, a, b) ((d) += MUL64(a, b))
#endif
#ifndef MLS64
# define MLS64(d, a, b) ((d) -= MUL64(a, b))
#endif
/* signed 16x16 -> 32 multiply add accumulate */
#ifndef MAC16
# define MAC16(rt, ra, rb) rt += (ra) * (rb)
#endif
/* signed 16x16 -> 32 multiply */
#ifndef MUL16
# define MUL16(ra, rb) ((ra) * (rb))
#endif
#ifndef MLS16
# define MLS16(rt, ra, rb) ((rt) -= (ra) * (rb))
#endif
#endif /* FFMPEG_MATHOPS_H */
@@ -2,19 +2,21 @@
* MDCT/IMDCT transforms
* Copyright (c) 2002 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
*/
#include "dsputil.h"
@@ -23,13 +25,52 @@
* MDCT/IMDCT transforms.
*/
// Generate a Kaiser-Bessel Derived Window.
#define BESSEL_I0_ITER 50 // default: 50 iterations of Bessel I0 approximation
void ff_kbd_window_init(float *window, float alpha, int n)
{
int i, j;
double sum = 0.0, bessel, tmp;
double local_window[n];
double alpha2 = (alpha * M_PI / n) * (alpha * M_PI / n);
for (i = 0; i < n; i++) {
tmp = i * (n - i) * alpha2;
bessel = 1.0;
for (j = BESSEL_I0_ITER; j > 0; j--)
bessel = bessel * tmp / (j * j) + 1;
sum += bessel;
local_window[i] = sum;
}
sum++;
for (i = 0; i < n; i++)
window[i] = sqrt(local_window[i] / sum);
}
DECLARE_ALIGNED(16, float, ff_sine_128 [ 128]);
DECLARE_ALIGNED(16, float, ff_sine_256 [ 256]);
DECLARE_ALIGNED(16, float, ff_sine_512 [ 512]);
DECLARE_ALIGNED(16, float, ff_sine_1024[1024]);
DECLARE_ALIGNED(16, float, ff_sine_2048[2048]);
float *ff_sine_windows[5] = {
ff_sine_128, ff_sine_256, ff_sine_512, ff_sine_1024, ff_sine_2048,
};
// Generate a sine window.
void ff_sine_window_init(float *window, int n) {
int i;
for(i = 0; i < n; i++)
window[i] = sin((i + 0.5) / (2 * n) * M_PI);
}
/**
* init MDCT or IMDCT computation.
*/
int ff_mdct_init(MDCTContext *s, int nbits, int inverse)
{
int n, n4, i;
float alpha;
double alpha;
memset(s, 0, sizeof(*s));
n = 1 << nbits;
@@ -48,7 +89,7 @@ int ff_mdct_init(MDCTContext *s, int nbits, int inverse)
s->tcos[i] = -cos(alpha);
s->tsin[i] = -sin(alpha);
}
if (fft_init(&s->fft, s->nbits - 2, inverse) < 0)
if (ff_fft_init(&s->fft, s->nbits - 2, inverse) < 0)
goto fail;
return 0;
fail:
@@ -60,29 +101,28 @@ int ff_mdct_init(MDCTContext *s, int nbits, int inverse)
/* complex multiplication: p = a * b */
#define CMUL(pre, pim, are, aim, bre, bim) \
{\
float _are = (are);\
float _aim = (aim);\
float _bre = (bre);\
float _bim = (bim);\
FFTSample _are = (are);\
FFTSample _aim = (aim);\
FFTSample _bre = (bre);\
FFTSample _bim = (bim);\
(pre) = _are * _bre - _aim * _bim;\
(pim) = _are * _bim + _aim * _bre;\
}
/**
* Compute inverse MDCT of size N = 2^nbits
* @param output N samples
* Compute the middle half of the inverse MDCT of size N = 2^nbits,
* thus excluding the parts that can be derived by symmetry
* @param output N/2 samples
* @param input N/2 samples
* @param tmp N/2 samples
*/
void ff_imdct_calc(MDCTContext *s, FFTSample *output,
const FFTSample *input, FFTSample *tmp)
void ff_imdct_half_c(MDCTContext *s, FFTSample *output, const FFTSample *input)
{
int k, n8, n4, n2, n, j;
const uint16_t *revtab = s->fft.revtab;
const FFTSample *tcos = s->tcos;
const FFTSample *tsin = s->tsin;
const FFTSample *in1, *in2;
FFTComplex *z = (FFTComplex *)tmp;
FFTComplex *z = (FFTComplex *)output;
n = 1 << s->nbits;
n2 = n >> 1;
@@ -98,25 +138,39 @@ void ff_imdct_calc(MDCTContext *s, FFTSample *output,
in1 += 2;
in2 -= 2;
}
fft_calc(&s->fft, z);
ff_fft_calc(&s->fft, z);
/* post rotation + reordering */
/* XXX: optimize */
for(k = 0; k < n4; k++) {
CMUL(z[k].re, z[k].im, z[k].re, z[k].im, tcos[k], tsin[k]);
}
output += n4;
for(k = 0; k < n8; k++) {
output[2*k] = -z[n8 + k].im;
output[n2-1-2*k] = z[n8 + k].im;
FFTSample r0, i0, r1, i1;
CMUL(r0, i1, z[n8-k-1].im, z[n8-k-1].re, tsin[n8-k-1], tcos[n8-k-1]);
CMUL(r1, i0, z[n8+k ].im, z[n8+k ].re, tsin[n8+k ], tcos[n8+k ]);
z[n8-k-1].re = r0;
z[n8-k-1].im = i0;
z[n8+k ].re = r1;
z[n8+k ].im = i1;
}
}
output[2*k+1] = z[n8-1-k].re;
output[n2-1-2*k-1] = -z[n8-1-k].re;
/**
* Compute inverse MDCT of size N = 2^nbits
* @param output N samples
* @param input N/2 samples
* @param tmp N/2 samples
*/
void ff_imdct_calc_c(MDCTContext *s, FFTSample *output, const FFTSample *input)
{
int k;
int n = 1 << s->nbits;
int n2 = n >> 1;
int n4 = n >> 2;
output[n2 + 2*k]=-z[k+n8].re;
output[n-1- 2*k]=-z[k+n8].re;
ff_imdct_half_c(s, output+n4, input);
output[n2 + 2*k+1]=z[n8-k-1].im;
output[n-2 - 2 * k] = z[n8-k-1].im;
for(k = 0; k < n4; k++) {
output[k] = -output[n2-k-1];
output[n-k-1] = output[n2+k];
}
}
@@ -126,15 +180,14 @@ void ff_imdct_calc(MDCTContext *s, FFTSample *output,
* @param out N/2 samples
* @param tmp temporary storage of N/2 samples
*/
void ff_mdct_calc(MDCTContext *s, FFTSample *out,
const FFTSample *input, FFTSample *tmp)
void ff_mdct_calc(MDCTContext *s, FFTSample *out, const FFTSample *input)
{
int i, j, n, n8, n4, n2, n3;
FFTSample re, im, re1, im1;
FFTSample re, im;
const uint16_t *revtab = s->fft.revtab;
const FFTSample *tcos = s->tcos;
const FFTSample *tsin = s->tsin;
FFTComplex *x = (FFTComplex *)tmp;
FFTComplex *x = (FFTComplex *)out;
n = 1 << s->nbits;
n2 = n >> 1;
@@ -155,15 +208,17 @@ void ff_mdct_calc(MDCTContext *s, FFTSample *out,
CMUL(x[j].re, x[j].im, re, im, -tcos[n8 + i], tsin[n8 + i]);
}
fft_calc(&s->fft, x);
ff_fft_calc(&s->fft, x);
/* post rotation */
for(i=0;i<n4;i++) {
re = x[i].re;
im = x[i].im;
CMUL(re1, im1, re, im, -tsin[i], -tcos[i]);
out[2*i] = im1;
out[n2-1-2*i] = re1;
for(i=0;i<n8;i++) {
FFTSample r0, i0, r1, i1;
CMUL(i1, r0, x[n8-i-1].re, x[n8-i-1].im, -tsin[n8-i-1], -tcos[n8-i-1]);
CMUL(i0, r1, x[n8+i ].re, x[n8+i ].im, -tsin[n8+i ], -tcos[n8+i ]);
x[n8-i-1].re = r0;
x[n8-i-1].im = i0;
x[n8+i ].re = r1;
x[n8+i ].im = i1;
}
}
@@ -171,5 +226,5 @@ void ff_mdct_end(MDCTContext *s)
{
av_freep(&s->tcos);
av_freep(&s->tsin);
fft_end(&s->fft);
ff_fft_end(&s->fft);
}
@@ -1,42 +1,41 @@
/*
* PSX MDEC codec
* Sony PlayStation MDEC (Motion DECoder)
* Copyright (c) 2003 Michael Niedermayer
*
* This library is free software; you can redistribute it and/or
* based upon code from Sebastian Jedruszkiewicz <elf@frogger.rules.pl>
*
* 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
*
* based upon code from Sebastian Jedruszkiewicz <elf@frogger.rules.pl>
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file mdec.c
* PSX MDEC codec.
* This is very similar to intra only MPEG1.
* Sony PlayStation MDEC (Motion DECoder)
* This is very similar to intra-only MPEG-1.
*/
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
//#undef NDEBUG
//#include <assert.h>
#include "mpeg12.h"
typedef struct MDECContext{
AVCodecContext *avctx;
DSPContext dsp;
AVFrame picture;
PutBitContext pb;
GetBitContext gb;
ScanTable scantable;
int version;
@@ -45,25 +44,25 @@ typedef struct MDECContext{
int mb_width;
int mb_height;
int mb_x, mb_y;
DCTELEM __align8 block[6][64];
uint16_t __align8 intra_matrix[64];
int __align8 q_intra_matrix[64];
DECLARE_ALIGNED_16(DCTELEM, block[6][64]);
DECLARE_ALIGNED_8(uint16_t, intra_matrix[64]);
DECLARE_ALIGNED_8(int, q_intra_matrix[64]);
uint8_t *bitstream_buffer;
int bitstream_buffer_size;
unsigned int bitstream_buffer_size;
int block_last_index[6];
} MDECContext;
//very similar to mpeg1
//very similar to MPEG-1
static inline int mdec_decode_block_intra(MDECContext *a, DCTELEM *block, int n)
{
int level, diff, i, j, run;
int component;
RLTable *rl = &rl_mpeg1;
RLTable *rl = &ff_rl_mpeg1;
uint8_t * const scantable= a->scantable.permutated;
const uint16_t *quant_matrix= ff_mpeg1_default_intra_matrix;
const int qscale= a->qscale;
/* DC coef */
/* DC coefficient */
if(a->version==2){
block[0]= 2*get_sbits(&a->gb, 10) + 1024;
}else{
@@ -74,22 +73,21 @@ static inline int mdec_decode_block_intra(MDECContext *a, DCTELEM *block, int n)
a->last_dc[component]+= diff;
block[0] = a->last_dc[component]<<3;
}
i = 0;
{
OPEN_READER(re, &a->gb);
/* now quantify & encode AC coefs */
OPEN_READER(re, &a->gb);
/* now quantify & encode AC coefficients */
for(;;) {
UPDATE_CACHE(re, &a->gb);
GET_RL_VLC(level, run, re, &a->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2);
GET_RL_VLC(level, run, re, &a->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0);
if(level == 127){
break;
} else if(level != 0) {
i += run;
j = scantable[i];
level= (level*qscale*quant_matrix[j])>>3;
// level= (level-1)|1;
level = (level ^ SHOW_SBITS(re, &a->gb, 1)) - SHOW_SBITS(re, &a->gb, 1);
LAST_SKIP_BITS(re, &a->gb, 1);
} else {
@@ -127,9 +125,9 @@ static inline int decode_mb(MDECContext *a, DCTELEM block[6][64]){
const int block_index[6]= {5,4,0,1,2,3};
a->dsp.clear_blocks(block[0]);
for(i=0; i<6; i++){
if( mdec_decode_block_intra(a, block[ block_index[i] ], block_index[i]) < 0)
if( mdec_decode_block_intra(a, block[ block_index[i] ], block_index[i]) < 0)
return -1;
}
return 0;
@@ -138,7 +136,7 @@ static inline int decode_mb(MDECContext *a, DCTELEM block[6][64]){
static inline void idct_put(MDECContext *a, int mb_x, int mb_y){
DCTELEM (*block)[64]= a->block;
int linesize= a->picture.linesize[0];
uint8_t *dest_y = a->picture.data[0] + (mb_y * 16* linesize ) + mb_x * 16;
uint8_t *dest_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8;
uint8_t *dest_cr = a->picture.data[2] + (mb_y * 8 * a->picture.linesize[2]) + mb_x * 8;
@@ -154,22 +152,15 @@ static inline void idct_put(MDECContext *a, int mb_x, int mb_y){
}
}
static int decode_frame(AVCodecContext *avctx,
static int decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
const uint8_t *buf, int buf_size)
{
MDECContext * const a = avctx->priv_data;
AVFrame *picture = data;
AVFrame * const p= (AVFrame*)&a->picture;
AVFrame * const p= &a->picture;
int i;
*data_size = 0;
/* special case for last picture */
if (buf_size == 0) {
return 0;
}
if(p->data[0])
avctx->release_buffer(avctx, p);
@@ -178,11 +169,8 @@ static int decode_frame(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
p->pict_type= I_TYPE;
p->pict_type= FF_I_TYPE;
p->key_frame= 1;
a->last_dc[0]=
a->last_dc[1]=
a->last_dc[2]= 0;
a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
for(i=0; i<buf_size; i+=2){
@@ -190,74 +178,68 @@ static int decode_frame(AVCodecContext *avctx,
a->bitstream_buffer[i+1]= buf[i ];
}
init_get_bits(&a->gb, a->bitstream_buffer, buf_size*8);
/* skip over 4 preamble bytes in stream (typically 0xXX 0xXX 0x00 0x38) */
skip_bits(&a->gb, 32);
a->qscale= get_bits(&a->gb, 16);
a->version= get_bits(&a->gb, 16);
// printf("qscale:%d (0x%X), version:%d (0x%X)\n", a->qscale, a->qscale, a->version, a->version);
a->last_dc[0]=
a->last_dc[1]=
a->last_dc[2]= 128;
for(a->mb_x=0; a->mb_x<a->mb_width; a->mb_x++){
for(a->mb_y=0; a->mb_y<a->mb_height; a->mb_y++){
if( decode_mb(a, a->block) <0)
return -1;
idct_put(a, a->mb_x, a->mb_y);
}
}
// p->quality= (32 + a->inv_qscale/2)/a->inv_qscale;
// memset(p->qscale_table, p->quality, p->qstride*a->mb_height);
*picture= *(AVFrame*)&a->picture;
p->quality= a->qscale * FF_QP2LAMBDA;
memset(p->qscale_table, a->qscale, p->qstride*a->mb_height);
*picture = a->picture;
*data_size = sizeof(AVPicture);
emms_c();
return (get_bits_count(&a->gb)+31)/32*4;
}
static void mdec_common_init(AVCodecContext *avctx){
static av_cold void mdec_common_init(AVCodecContext *avctx){
MDECContext * const a = avctx->priv_data;
dsputil_init(&a->dsp, avctx);
a->mb_width = (avctx->width + 15) / 16;
a->mb_height = (avctx->height + 15) / 16;
a->mb_width = (avctx->coded_width + 15) / 16;
a->mb_height = (avctx->coded_height + 15) / 16;
avctx->coded_frame= (AVFrame*)&a->picture;
avctx->coded_frame= &a->picture;
a->avctx= avctx;
}
static int decode_init(AVCodecContext *avctx){
static av_cold int decode_init(AVCodecContext *avctx){
MDECContext * const a = avctx->priv_data;
AVFrame *p= (AVFrame*)&a->picture;
AVFrame *p= &a->picture;
mdec_common_init(avctx);
init_vlcs();
ff_mpeg12_init_vlcs();
ff_init_scantable(a->dsp.idct_permutation, &a->scantable, ff_zigzag_direct);
/*
for(i=0; i<64; i++){
int index= ff_zigzag_direct[i];
a->intra_matrix[i]= 64*ff_mpeg1_default_intra_matrix[index] / a->inv_qscale;
}
*/
p->qstride= a->mb_width;
p->qscale_table= av_mallocz( p->qstride * a->mb_height);
avctx->pix_fmt= PIX_FMT_YUV420P;
return 0;
}
static int decode_end(AVCodecContext *avctx){
static av_cold int decode_end(AVCodecContext *avctx){
MDECContext * const a = avctx->priv_data;
av_freep(&a->bitstream_buffer);
av_freep(&a->picture.qscale_table);
a->bitstream_buffer_size=0;
avcodec_default_free_buffers(avctx);
return 0;
}
@@ -272,5 +254,6 @@ AVCodec mdec_decoder = {
decode_end,
decode_frame,
CODEC_CAP_DR1,
.long_name= NULL_IF_CONFIG_SMALL("Sony PlayStation MDEC (Motion DECoder)"),
};
@@ -0,0 +1,390 @@
/*
* Copyright (C) 2005 Ole André Vadla Ravnås <oleavr@gmail.com>
* Copyright (C) 2008 Ramiro Polla <ramiro@lisha.ufsc.br>
*
* 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 <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "avcodec.h"
#include "bitstream.h"
#include "bytestream.h"
#include "dsputil.h"
#define MIMIC_HEADER_SIZE 20
typedef struct {
AVCodecContext *avctx;
int num_vblocks[3];
int num_hblocks[3];
uint8_t *swap_buf;
int swap_buf_size;
int cur_index;
int prev_index;
AVFrame buf_ptrs [16];
AVPicture flipped_ptrs[16];
DECLARE_ALIGNED_16(DCTELEM, dct_block[64]);
GetBitContext gb;
ScanTable scantable;
DSPContext dsp;
VLC vlc;
} MimicContext;
static const uint32_t huffcodes[] = {
0x0000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000b,
0x0000001b, 0x00000038, 0x00000078, 0x00000079, 0x0000007a, 0x000000f9,
0x000000fa, 0x000003fb, 0x000007f8, 0x000007f9, 0x000007fa, 0x000007fb,
0x00000ff8, 0x00000ff9, 0x00000001, 0x00000039, 0x0000007b, 0x000000fb,
0x000001f8, 0x000001f9, 0x00000ffa, 0x00000ffb, 0x00001ff8, 0x00001ff9,
0x00001ffa, 0x00001ffb, 0x00003ff8, 0x00003ff9, 0x00003ffa, 0x00000000,
0x00000004, 0x0000003a, 0x000001fa, 0x00003ffb, 0x00007ff8, 0x00007ff9,
0x00007ffa, 0x00007ffb, 0x0000fff8, 0x0000fff9, 0x0000fffa, 0x0000fffb,
0x0001fff8, 0x0001fff9, 0x0001fffa, 0x00000000, 0x0000000c, 0x000000f8,
0x000001fb, 0x0001fffb, 0x0003fff8, 0x0003fff9, 0x0003fffa, 0x0003fffb,
0x0007fff8, 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9,
0x000ffffa, 0x00000000, 0x0000001a, 0x000003f8, 0x000ffffb, 0x001ffff8,
0x001ffff9, 0x001ffffa, 0x001ffffb, 0x003ffff8, 0x003ffff9, 0x003ffffa,
0x003ffffb, 0x007ffff8, 0x007ffff9, 0x007ffffa, 0x007ffffb, 0x00000000,
0x0000003b, 0x000003f9, 0x00fffff8, 0x00fffff9, 0x00fffffa, 0x00fffffb,
0x01fffff8, 0x01fffff9, 0x01fffffa, 0x01fffffb, 0x03fffff8, 0x03fffff9,
0x03fffffa, 0x03fffffb, 0x07fffff8, 0x00000000, 0x000003fa, 0x07fffff9,
0x07fffffa, 0x07fffffb, 0x0ffffff8, 0x0ffffff9, 0x0ffffffa, 0x0ffffffb,
0x1ffffff8, 0x1ffffff9, 0x1ffffffa, 0x1ffffffb, 0x3ffffff8, 0x3ffffff9,
0x3ffffffa,
};
static const uint8_t huffbits[] = {
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 4, 5, 6, 7, 7, 7, 8,
8, 10, 11, 11, 11, 11, 12, 12, 2, 6, 7, 8,
9, 9, 12, 12, 13, 13, 13, 13, 14, 14, 14, 0,
3, 6, 9, 14, 15, 15, 15, 15, 16, 16, 16, 16,
17, 17, 17, 0, 4, 8, 9, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 0, 5, 10, 20, 21,
21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 0,
6, 10, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26,
26, 26, 27, 0, 10, 27, 27, 27, 28, 28, 28, 28,
29, 29, 29, 29, 30, 30, 30,
};
static const uint8_t col_zag[64] = {
0, 8, 1, 2, 9, 16, 24, 17,
10, 3, 4, 11, 18, 25, 32, 40,
33, 26, 19, 12, 5, 6, 13, 20,
27, 34, 41, 48, 56, 49, 42, 35,
28, 21, 14, 7, 15, 22, 29, 36,
43, 50, 57, 58, 51, 44, 37, 30,
23, 31, 38, 45, 52, 59, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63,
};
static av_cold int mimic_decode_init(AVCodecContext *avctx)
{
MimicContext *ctx = avctx->priv_data;
ctx->prev_index = 0;
ctx->cur_index = 15;
if(init_vlc(&ctx->vlc, 11, sizeof(huffbits)/sizeof(huffbits[0]),
huffbits, 1, 1, huffcodes, 4, 4, 0)) {
av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n");
return -1;
}
dsputil_init(&ctx->dsp, avctx);
ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, col_zag);
return 0;
}
const static int8_t vlcdec_lookup[9][64] = {
{ 0, },
{ -1, 1, },
{ -3, 3, -2, 2, },
{ -7, 7, -6, 6, -5, 5, -4, 4, },
{ -15, 15, -14, 14, -13, 13, -12, 12,
-11, 11, -10, 10, -9, 9, -8, 8, },
{ -31, 31, -30, 30, -29, 29, -28, 28,
-27, 27, -26, 26, -25, 25, -24, 24,
-23, 23, -22, 22, -21, 21, -20, 20,
-19, 19, -18, 18, -17, 17, -16, 16, },
{ -63, 63, -62, 62, -61, 61, -60, 60,
-59, 59, -58, 58, -57, 57, -56, 56,
-55, 55, -54, 54, -53, 53, -52, 52,
-51, 51, -50, 50, -49, 49, -48, 48,
-47, 47, -46, 46, -45, 45, -44, 44,
-43, 43, -42, 42, -41, 41, -40, 40,
-39, 39, -38, 38, -37, 37, -36, 36,
-35, 35, -34, 34, -33, 33, -32, 32, },
{ -127, 127, -126, 126, -125, 125, -124, 124,
-123, 123, -122, 122, -121, 121, -120, 120,
-119, 119, -118, 118, -117, 117, -116, 116,
-115, 115, -114, 114, -113, 113, -112, 112,
-111, 111, -110, 110, -109, 109, -108, 108,
-107, 107, -106, 106, -105, 105, -104, 104,
-103, 103, -102, 102, -101, 101, -100, 100,
-99, 99, -98, 98, -97, 97, -96, 96, },
{ -95, 95, -94, 94, -93, 93, -92, 92,
-91, 91, -90, 90, -89, 89, -88, 88,
-87, 87, -86, 86, -85, 85, -84, 84,
-83, 83, -82, 82, -81, 81, -80, 80,
-79, 79, -78, 78, -77, 77, -76, 76,
-75, 75, -74, 74, -73, 73, -72, 72,
-71, 71, -70, 70, -69, 69, -68, 68,
-67, 67, -66, 66, -65, 65, -64, 64, },
};
static int vlc_decode_block(MimicContext *ctx, int num_coeffs, int qscale)
{
DCTELEM *block = ctx->dct_block;
unsigned int pos;
memset(block, 0, 64 * sizeof(DCTELEM));
block[0] = get_bits(&ctx->gb, 8) << 3;
for(pos = 1; pos < num_coeffs; pos++) {
uint32_t vlc, num_bits;
int value;
int coeff;
vlc = get_vlc2(&ctx->gb, ctx->vlc.table, ctx->vlc.bits, 3);
if(!vlc) /* end-of-block code */
return 1;
if(vlc == -1)
return 0;
/* pos_add and num_bits are coded in the vlc code */
pos += vlc&15; // pos_add
num_bits = vlc>>4; // num_bits
if(pos >= 64)
return 0;
value = get_bits(&ctx->gb, num_bits);
/* FFmpeg's IDCT behaves somewhat different from the original code, so
* a factor of 4 was added to the input */
coeff = vlcdec_lookup[num_bits][value];
if(pos<3)
coeff <<= 4;
else /* TODO Use >> 10 instead of / 1001 */
coeff = (coeff * qscale) / 1001;
block[ctx->scantable.permutated[pos]] = coeff;
}
return 1;
}
static int decode(MimicContext *ctx, int quality, int num_coeffs,
int is_iframe)
{
int y, x, plane;
for(plane = 0; plane < 3; plane++) {
const int is_chroma = !!plane;
const int qscale = av_clip(10000-quality,is_chroma?1000:2000,10000)<<2;
const int stride = ctx->flipped_ptrs[ctx->cur_index].linesize[plane];
const uint8_t *src = ctx->flipped_ptrs[ctx->prev_index].data[plane];
uint8_t *dst = ctx->flipped_ptrs[ctx->cur_index ].data[plane];
for(y = 0; y < ctx->num_vblocks[plane]; y++) {
for(x = 0; x < ctx->num_hblocks[plane]; x++) {
/* Check for a change condition in the current block.
* - iframes always change.
* - Luma plane changes on get_bits1 == 0
* - Chroma planes change on get_bits1 == 1 */
if(is_iframe || get_bits1(&ctx->gb) == is_chroma) {
/* Luma planes may use a backreference from the 15 last
* frames preceding the previous. (get_bits1 == 1)
* Chroma planes don't use backreferences. */
if(is_chroma || is_iframe || !get_bits1(&ctx->gb)) {
if(!vlc_decode_block(ctx, num_coeffs, qscale))
return 0;
ctx->dsp.idct_put(dst, stride, ctx->dct_block);
} else {
unsigned int backref = get_bits(&ctx->gb, 4);
int index = (ctx->cur_index+backref)&15;
uint8_t *p = ctx->flipped_ptrs[index].data[0];
if(p) {
p += src -
ctx->flipped_ptrs[ctx->prev_index].data[plane];
ctx->dsp.put_pixels_tab[1][0](dst, p, stride, 8);
} else {
av_log(ctx->avctx, AV_LOG_ERROR,
"No such backreference! Buggy sample.\n");
}
}
} else {
ctx->dsp.put_pixels_tab[1][0](dst, src, stride, 8);
}
src += 8;
dst += 8;
}
src += (stride - ctx->num_hblocks[plane])<<3;
dst += (stride - ctx->num_hblocks[plane])<<3;
}
}
return 1;
}
/**
* Flip the buffer upside-down and put it in the YVU order to match the
* way Mimic encodes frames.
*/
static void prepare_avpic(MimicContext *ctx, AVPicture *dst, AVPicture *src)
{
int i;
dst->data[0] = src->data[0]+( ctx->avctx->height -1)*src->linesize[0];
dst->data[1] = src->data[2]+((ctx->avctx->height>>1)-1)*src->linesize[2];
dst->data[2] = src->data[1]+((ctx->avctx->height>>1)-1)*src->linesize[1];
for(i = 0; i < 3; i++)
dst->linesize[i] = -src->linesize[i];
}
static int mimic_decode_frame(AVCodecContext *avctx, void *data,
int *data_size, const uint8_t *buf, int buf_size)
{
MimicContext *ctx = avctx->priv_data;
int is_pframe;
int width, height;
int quality, num_coeffs;
int swap_buf_size = buf_size - MIMIC_HEADER_SIZE;
if(buf_size < MIMIC_HEADER_SIZE) {
av_log(avctx, AV_LOG_ERROR, "insufficient data\n");
return -1;
}
buf += 2; /* some constant (always 256) */
quality = bytestream_get_le16(&buf);
width = bytestream_get_le16(&buf);
height = bytestream_get_le16(&buf);
buf += 4; /* some constant */
is_pframe = bytestream_get_le32(&buf);
num_coeffs = bytestream_get_byte(&buf);
buf += 3; /* some constant */
if(!ctx->avctx) {
int i;
if(!(width == 160 && height == 120) &&
!(width == 320 && height == 240)) {
av_log(avctx, AV_LOG_ERROR, "invalid width/height!\n");
return -1;
}
ctx->avctx = avctx;
avctx->width = width;
avctx->height = height;
avctx->pix_fmt = PIX_FMT_YUV420P;
for(i = 0; i < 3; i++) {
ctx->num_vblocks[i] = -((-height) >> (3 + !!i));
ctx->num_hblocks[i] = width >> (3 + !!i) ;
}
} else if(width != ctx->avctx->width || height != ctx->avctx->height) {
av_log(avctx, AV_LOG_ERROR, "resolution changing is not supported\n");
return -1;
}
if(is_pframe && !ctx->buf_ptrs[ctx->prev_index].data[0]) {
av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n");
return -1;
}
ctx->buf_ptrs[ctx->cur_index].reference = 1;
if(avctx->get_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index])) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index],
(AVPicture*) &ctx->buf_ptrs[ctx->cur_index]);
ctx->swap_buf = av_fast_realloc(ctx->swap_buf, &ctx->swap_buf_size,
swap_buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
if(!ctx->swap_buf)
return AVERROR_NOMEM;
ctx->dsp.bswap_buf((uint32_t*)ctx->swap_buf,
(const uint32_t*) buf,
swap_buf_size>>2);
init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3);
if(!decode(ctx, quality, num_coeffs, !is_pframe)) {
avctx->release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
return -1;
}
ctx->buf_ptrs[ctx->cur_index].pict_type = is_pframe ? FF_P_TYPE:FF_I_TYPE;
*(AVFrame*)data = ctx->buf_ptrs[ctx->cur_index];
*data_size = sizeof(AVFrame);
ctx->prev_index = ctx->cur_index;
ctx->cur_index--;
ctx->cur_index &= 15;
/* Only release frames that aren't used for backreferences anymore */
if(ctx->buf_ptrs[ctx->cur_index].data[0])
avctx->release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
return buf_size;
}
static av_cold int mimic_decode_end(AVCodecContext *avctx)
{
MimicContext *ctx = avctx->priv_data;
int i;
av_free(ctx->swap_buf);
for(i = 0; i < 16; i++)
if(ctx->buf_ptrs[i].data[0])
avctx->release_buffer(avctx, &ctx->buf_ptrs[i]);
free_vlc(&ctx->vlc);
return 0;
}
AVCodec mimic_decoder = {
"mimic",
CODEC_TYPE_VIDEO,
CODEC_ID_MIMIC,
sizeof(MimicContext),
mimic_decode_init,
NULL,
mimic_decode_end,
mimic_decode_frame,
CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("Mimic"),
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,155 @@
/*
* MJPEG encoder and decoder
* Copyright (c) 2000, 2001 Fabrice Bellard.
* Copyright (c) 2003 Alex Beregszaszi
* Copyright (c) 2003-2004 Michael Niedermayer
*
* Support for external huffman table, various fixes (AVID workaround),
* aspecting, new decode_frame mechanism and apple mjpeg-b support
* by Alex Beregszaszi
*
* 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 mjpeg.h
* MJPEG encoder and decoder.
*/
#ifndef FFMPEG_MJPEG_H
#define FFMPEG_MJPEG_H
#include "avcodec.h"
#include "bitstream.h"
/* JPEG marker codes */
typedef enum {
/* start of frame */
SOF0 = 0xc0, /* baseline */
SOF1 = 0xc1, /* extended sequential, huffman */
SOF2 = 0xc2, /* progressive, huffman */
SOF3 = 0xc3, /* lossless, huffman */
SOF5 = 0xc5, /* differential sequential, huffman */
SOF6 = 0xc6, /* differential progressive, huffman */
SOF7 = 0xc7, /* differential lossless, huffman */
JPG = 0xc8, /* reserved for JPEG extension */
SOF9 = 0xc9, /* extended sequential, arithmetic */
SOF10 = 0xca, /* progressive, arithmetic */
SOF11 = 0xcb, /* lossless, arithmetic */
SOF13 = 0xcd, /* differential sequential, arithmetic */
SOF14 = 0xce, /* differential progressive, arithmetic */
SOF15 = 0xcf, /* differential lossless, arithmetic */
DHT = 0xc4, /* define huffman tables */
DAC = 0xcc, /* define arithmetic-coding conditioning */
/* restart with modulo 8 count "m" */
RST0 = 0xd0,
RST1 = 0xd1,
RST2 = 0xd2,
RST3 = 0xd3,
RST4 = 0xd4,
RST5 = 0xd5,
RST6 = 0xd6,
RST7 = 0xd7,
SOI = 0xd8, /* start of image */
EOI = 0xd9, /* end of image */
SOS = 0xda, /* start of scan */
DQT = 0xdb, /* define quantization tables */
DNL = 0xdc, /* define number of lines */
DRI = 0xdd, /* define restart interval */
DHP = 0xde, /* define hierarchical progression */
EXP = 0xdf, /* expand reference components */
APP0 = 0xe0,
APP1 = 0xe1,
APP2 = 0xe2,
APP3 = 0xe3,
APP4 = 0xe4,
APP5 = 0xe5,
APP6 = 0xe6,
APP7 = 0xe7,
APP8 = 0xe8,
APP9 = 0xe9,
APP10 = 0xea,
APP11 = 0xeb,
APP12 = 0xec,
APP13 = 0xed,
APP14 = 0xee,
APP15 = 0xef,
JPG0 = 0xf0,
JPG1 = 0xf1,
JPG2 = 0xf2,
JPG3 = 0xf3,
JPG4 = 0xf4,
JPG5 = 0xf5,
JPG6 = 0xf6,
SOF48 = 0xf7, ///< JPEG-LS
LSE = 0xf8, ///< JPEG-LS extension parameters
JPG9 = 0xf9,
JPG10 = 0xfa,
JPG11 = 0xfb,
JPG12 = 0xfc,
JPG13 = 0xfd,
COM = 0xfe, /* comment */
TEM = 0x01, /* temporary private use for arithmetic coding */
/* 0x02 -> 0xbf reserved */
} JPEG_MARKER;
static inline void put_marker(PutBitContext *p, int code)
{
put_bits(p, 8, 0xff);
put_bits(p, 8, code);
}
#define PREDICT(ret, topleft, top, left, predictor)\
switch(predictor){\
case 1: ret= left; break;\
case 2: ret= top; break;\
case 3: ret= topleft; break;\
case 4: ret= left + top - topleft; break;\
case 5: ret= left + ((top - topleft)>>1); break;\
case 6: ret= top + ((left - topleft)>>1); break;\
default:\
case 7: ret= (left + top)>>1; break;\
}
extern const uint8_t ff_mjpeg_bits_dc_luminance[];
extern const uint8_t ff_mjpeg_val_dc[];
extern const uint8_t ff_mjpeg_bits_dc_chrominance[];
extern const uint8_t ff_mjpeg_bits_ac_luminance[];
extern const uint8_t ff_mjpeg_val_ac_luminance[];
extern const uint8_t ff_mjpeg_bits_ac_chrominance[];
extern const uint8_t ff_mjpeg_val_ac_chrominance[];
void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code,
const uint8_t *bits_table,
const uint8_t *val_table);
#endif /* FFMPEG_MJPEG_H */
@@ -0,0 +1,101 @@
/*
* MJPEG parser
* Copyright (c) 2000, 2001 Fabrice Bellard.
* Copyright (c) 2003 Alex Beregszaszi
* Copyright (c) 2003-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 mjpeg_parser.c
* MJPEG parser.
*/
#include "parser.h"
/**
* finds the end of the current frame in the bitstream.
* @return the position of the first byte of the next frame, or -1
*/
static int find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){
int vop_found, i;
uint16_t state;
vop_found= pc->frame_start_found;
state= pc->state;
i=0;
if(!vop_found){
for(i=0; i<buf_size; i++){
state= (state<<8) | buf[i];
if(state == 0xFFD8){
i++;
vop_found=1;
break;
}
}
}
if(vop_found){
/* EOF considered as end of frame */
if (buf_size == 0)
return 0;
for(; i<buf_size; i++){
state= (state<<8) | buf[i];
if(state == 0xFFD8){
pc->frame_start_found=0;
pc->state=0;
return i-1;
}
}
}
pc->frame_start_found= vop_found;
pc->state= state;
return END_NOT_FOUND;
}
static int jpeg_parse(AVCodecParserContext *s,
AVCodecContext *avctx,
const uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size)
{
ParseContext *pc = s->priv_data;
int next;
next= find_frame_end(pc, buf, buf_size);
if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
*poutbuf = NULL;
*poutbuf_size = 0;
return buf_size;
}
*poutbuf = buf;
*poutbuf_size = buf_size;
return next;
}
AVCodecParser mjpeg_parser = {
{ CODEC_ID_MJPEG },
sizeof(ParseContext),
NULL,
jpeg_parse,
ff_parse_close,
};
@@ -0,0 +1,92 @@
/*
* MJPEG A dump header bitstream filter
* Copyright (c) 2006 Baptiste Coudurier.
*
* 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 mjpega_dump_header_bsf.c
* MJPEG A dump header bitstream filter
* modifies bitstream to be decoded by quicktime
*/
#include "avcodec.h"
#include "bytestream.h"
#include "mjpeg.h"
static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe)
{
uint8_t *poutbufp;
int i;
if (avctx->codec_id != CODEC_ID_MJPEG) {
av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n");
return 0;
}
*poutbuf_size = 0;
*poutbuf = av_malloc(buf_size + 44 + FF_INPUT_BUFFER_PADDING_SIZE);
poutbufp = *poutbuf;
bytestream_put_byte(&poutbufp, 0xff);
bytestream_put_byte(&poutbufp, SOI);
bytestream_put_byte(&poutbufp, 0xff);
bytestream_put_byte(&poutbufp, APP1);
bytestream_put_be16(&poutbufp, 42); /* size */
bytestream_put_be32(&poutbufp, 0);
bytestream_put_buffer(&poutbufp, "mjpg", 4);
bytestream_put_be32(&poutbufp, buf_size + 44); /* field size */
bytestream_put_be32(&poutbufp, buf_size + 44); /* pad field size */
bytestream_put_be32(&poutbufp, 0); /* next ptr */
for (i = 0; i < buf_size - 1; i++) {
if (buf[i] == 0xff) {
switch (buf[i + 1]) {
case DQT: /* quant off */
case DHT: /* huff off */
case SOF0: /* image off */
bytestream_put_be32(&poutbufp, i + 46);
break;
case SOS:
bytestream_put_be32(&poutbufp, i + 46); /* scan off */
bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */
bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */
*poutbuf_size = poutbufp - *poutbuf;
return 1;
case APP1:
if (i + 8 < buf_size && AV_RL32(buf + i + 8) == ff_get_fourcc("mjpg")) {
av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n");
memcpy(*poutbuf, buf, buf_size);
*poutbuf_size = buf_size;
return 1;
}
}
}
}
av_freep(poutbuf);
av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n");
return 0;
}
AVBitStreamFilter mjpega_dump_header_bsf = {
"mjpegadump",
0,
mjpega_dump_header,
};
@@ -0,0 +1,150 @@
/*
* Apple MJPEG-B decoder
* Copyright (c) 2002 Alex Beregszaszi
*
* 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 mjpegbdec.c
* Apple MJPEG-B decoder.
*/
#include "avcodec.h"
#include "mjpeg.h"
#include "mjpegdec.h"
static int mjpegb_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
MJpegDecodeContext *s = avctx->priv_data;
const uint8_t *buf_end, *buf_ptr;
AVFrame *picture = data;
GetBitContext hgb; /* for the header */
uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs;
uint32_t field_size, sod_offs;
buf_ptr = buf;
buf_end = buf + buf_size;
read_header:
/* reset on every SOI */
s->restart_interval = 0;
s->restart_count = 0;
s->mjpb_skiptosod = 0;
init_get_bits(&hgb, buf_ptr, /*buf_size*/(buf_end - buf_ptr)*8);
skip_bits(&hgb, 32); /* reserved zeros */
if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g'))
{
av_log(avctx, AV_LOG_WARNING, "not mjpeg-b (bad fourcc)\n");
return 0;
}
field_size = get_bits_long(&hgb, 32); /* field size */
av_log(avctx, AV_LOG_DEBUG, "field size: 0x%x\n", field_size);
skip_bits(&hgb, 32); /* padded field size */
second_field_offs = get_bits_long(&hgb, 32);
av_log(avctx, AV_LOG_DEBUG, "second field offs: 0x%x\n", second_field_offs);
dqt_offs = get_bits_long(&hgb, 32);
av_log(avctx, AV_LOG_DEBUG, "dqt offs: 0x%x\n", dqt_offs);
if (dqt_offs)
{
init_get_bits(&s->gb, buf_ptr+dqt_offs, (buf_end - (buf_ptr+dqt_offs))*8);
s->start_code = DQT;
ff_mjpeg_decode_dqt(s);
}
dht_offs = get_bits_long(&hgb, 32);
av_log(avctx, AV_LOG_DEBUG, "dht offs: 0x%x\n", dht_offs);
if (dht_offs)
{
init_get_bits(&s->gb, buf_ptr+dht_offs, (buf_end - (buf_ptr+dht_offs))*8);
s->start_code = DHT;
ff_mjpeg_decode_dht(s);
}
sof_offs = get_bits_long(&hgb, 32);
av_log(avctx, AV_LOG_DEBUG, "sof offs: 0x%x\n", sof_offs);
if (sof_offs)
{
init_get_bits(&s->gb, buf_ptr+sof_offs, (buf_end - (buf_ptr+sof_offs))*8);
s->start_code = SOF0;
if (ff_mjpeg_decode_sof(s) < 0)
return -1;
}
sos_offs = get_bits_long(&hgb, 32);
av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%x\n", sos_offs);
sod_offs = get_bits_long(&hgb, 32);
av_log(avctx, AV_LOG_DEBUG, "sod offs: 0x%x\n", sod_offs);
if (sos_offs)
{
// init_get_bits(&s->gb, buf+sos_offs, (buf_end - (buf+sos_offs))*8);
init_get_bits(&s->gb, buf_ptr+sos_offs, field_size*8);
s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16));
s->start_code = SOS;
ff_mjpeg_decode_sos(s);
}
if (s->interlaced) {
s->bottom_field ^= 1;
/* if not bottom field, do not output image yet */
if (s->bottom_field != s->interlace_polarity && second_field_offs)
{
buf_ptr = buf + second_field_offs;
second_field_offs = 0;
goto read_header;
}
}
//XXX FIXME factorize, this looks very similar to the EOI code
*picture= s->picture;
*data_size = sizeof(AVFrame);
if(!s->lossless){
picture->quality= FFMAX3(s->qscale[0], s->qscale[1], s->qscale[2]);
picture->qstride= 0;
picture->qscale_table= s->qscale_table;
memset(picture->qscale_table, picture->quality, (s->width+15)/16);
if(avctx->debug & FF_DEBUG_QP)
av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
picture->quality*= FF_QP2LAMBDA;
}
return buf_ptr - buf;
}
AVCodec mjpegb_decoder = {
"mjpegb",
CODEC_TYPE_VIDEO,
CODEC_ID_MJPEGB,
sizeof(MJpegDecodeContext),
ff_mjpeg_decode_init,
NULL,
ff_mjpeg_decode_end,
mjpegb_decode_frame,
CODEC_CAP_DR1,
NULL,
.long_name = NULL_IF_CONFIG_SMALL("Apple MJPEG-B"),
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,111 @@
/*
* MJPEG decoder
* Copyright (c) 2000, 2001 Fabrice Bellard.
* Copyright (c) 2003 Alex Beregszaszi
* Copyright (c) 2003-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 mjpegdec.h
* MJPEG decoder.
*/
#ifndef FFMPEG_MJPEGDEC_H
#define FFMPEG_MJPEGDEC_H
#include "avcodec.h"
#include "bitstream.h"
#include "dsputil.h"
#define MAX_COMPONENTS 4
typedef struct MJpegDecodeContext {
AVCodecContext *avctx;
GetBitContext gb;
int start_code; /* current start code */
int buffer_size;
uint8_t *buffer;
int16_t quant_matrixes[4][64];
VLC vlcs[2][4];
int qscale[4]; ///< quantizer scale calculated from quant_matrixes
int org_height; /* size given at codec init */
int first_picture; /* true if decoding first picture */
int interlaced; /* true if interlaced */
int bottom_field; /* true if bottom field */
int lossless;
int ls;
int progressive;
int rgb;
int rct; /* standard rct */
int pegasus_rct; /* pegasus reversible colorspace transform */
int bits; /* bits per component */
int maxval;
int near; ///< near lossless bound (si 0 for lossless)
int t1,t2,t3;
int reset; ///< context halfing intervall ?rename
int width, height;
int mb_width, mb_height;
int nb_components;
int component_id[MAX_COMPONENTS];
int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */
int v_count[MAX_COMPONENTS];
int comp_index[MAX_COMPONENTS];
int dc_index[MAX_COMPONENTS];
int ac_index[MAX_COMPONENTS];
int nb_blocks[MAX_COMPONENTS];
int h_scount[MAX_COMPONENTS];
int v_scount[MAX_COMPONENTS];
int h_max, v_max; /* maximum h and v counts */
int quant_index[4]; /* quant table index for each component */
int last_dc[MAX_COMPONENTS]; /* last DEQUANTIZED dc (XXX: am I right to do that ?) */
AVFrame picture; /* picture structure */
int linesize[MAX_COMPONENTS]; ///< linesize << interlaced
int8_t *qscale_table;
DECLARE_ALIGNED_16(DCTELEM, block[64]);
ScanTable scantable;
DSPContext dsp;
int restart_interval;
int restart_count;
int buggy_avid;
int cs_itu601;
int interlace_polarity;
int mjpb_skiptosod;
int cur_scan; /* current scan, used by JPEG-LS */
} MJpegDecodeContext;
int ff_mjpeg_decode_init(AVCodecContext *avctx);
int ff_mjpeg_decode_end(AVCodecContext *avctx);
int ff_mjpeg_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size);
int ff_mjpeg_decode_dqt(MJpegDecodeContext *s);
int ff_mjpeg_decode_dht(MJpegDecodeContext *s);
int ff_mjpeg_decode_sof(MJpegDecodeContext *s);
int ff_mjpeg_decode_sos(MJpegDecodeContext *s);
#endif /* FFMPEG_MJPEGDEC_H */
@@ -0,0 +1,459 @@
/*
* MJPEG encoder
* Copyright (c) 2000, 2001 Fabrice Bellard.
* Copyright (c) 2003 Alex Beregszaszi
* Copyright (c) 2003-2004 Michael Niedermayer
*
* Support for external huffman table, various fixes (AVID workaround),
* aspecting, new decode_frame mechanism and apple mjpeg-b support
* by Alex Beregszaszi
*
* 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 mjpegenc.c
* MJPEG encoder.
*/
//#define DEBUG
#include <assert.h>
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
#include "mjpeg.h"
#include "mjpegenc.h"
/* use two quantizer tables (one for luminance and one for chrominance) */
/* not yet working */
#undef TWOMATRIXES
av_cold int ff_mjpeg_encode_init(MpegEncContext *s)
{
MJpegContext *m;
m = av_malloc(sizeof(MJpegContext));
if (!m)
return -1;
s->min_qcoeff=-1023;
s->max_qcoeff= 1023;
/* build all the huffman tables */
ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance,
m->huff_code_dc_luminance,
ff_mjpeg_bits_dc_luminance,
ff_mjpeg_val_dc);
ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance,
m->huff_code_dc_chrominance,
ff_mjpeg_bits_dc_chrominance,
ff_mjpeg_val_dc);
ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance,
m->huff_code_ac_luminance,
ff_mjpeg_bits_ac_luminance,
ff_mjpeg_val_ac_luminance);
ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance,
m->huff_code_ac_chrominance,
ff_mjpeg_bits_ac_chrominance,
ff_mjpeg_val_ac_chrominance);
s->mjpeg_ctx = m;
return 0;
}
void ff_mjpeg_encode_close(MpegEncContext *s)
{
av_free(s->mjpeg_ctx);
}
/* table_class: 0 = DC coef, 1 = AC coefs */
static int put_huffman_table(MpegEncContext *s, int table_class, int table_id,
const uint8_t *bits_table, const uint8_t *value_table)
{
PutBitContext *p = &s->pb;
int n, i;
put_bits(p, 4, table_class);
put_bits(p, 4, table_id);
n = 0;
for(i=1;i<=16;i++) {
n += bits_table[i];
put_bits(p, 8, bits_table[i]);
}
for(i=0;i<n;i++)
put_bits(p, 8, value_table[i]);
return n + 17;
}
static void jpeg_table_header(MpegEncContext *s)
{
PutBitContext *p = &s->pb;
int i, j, size;
uint8_t *ptr;
/* quant matrixes */
put_marker(p, DQT);
#ifdef TWOMATRIXES
put_bits(p, 16, 2 + 2 * (1 + 64));
#else
put_bits(p, 16, 2 + 1 * (1 + 64));
#endif
put_bits(p, 4, 0); /* 8 bit precision */
put_bits(p, 4, 0); /* table 0 */
for(i=0;i<64;i++) {
j = s->intra_scantable.permutated[i];
put_bits(p, 8, s->intra_matrix[j]);
}
#ifdef TWOMATRIXES
put_bits(p, 4, 0); /* 8 bit precision */
put_bits(p, 4, 1); /* table 1 */
for(i=0;i<64;i++) {
j = s->intra_scantable.permutated[i];
put_bits(p, 8, s->chroma_intra_matrix[j]);
}
#endif
/* huffman table */
put_marker(p, DHT);
flush_put_bits(p);
ptr = pbBufPtr(p);
put_bits(p, 16, 0); /* patched later */
size = 2;
size += put_huffman_table(s, 0, 0, ff_mjpeg_bits_dc_luminance,
ff_mjpeg_val_dc);
size += put_huffman_table(s, 0, 1, ff_mjpeg_bits_dc_chrominance,
ff_mjpeg_val_dc);
size += put_huffman_table(s, 1, 0, ff_mjpeg_bits_ac_luminance,
ff_mjpeg_val_ac_luminance);
size += put_huffman_table(s, 1, 1, ff_mjpeg_bits_ac_chrominance,
ff_mjpeg_val_ac_chrominance);
AV_WB16(ptr, size);
}
static void jpeg_put_comments(MpegEncContext *s)
{
PutBitContext *p = &s->pb;
int size;
uint8_t *ptr;
if (s->aspect_ratio_info /* && !lossless */)
{
/* JFIF header */
put_marker(p, APP0);
put_bits(p, 16, 16);
ff_put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */
put_bits(p, 16, 0x0201); /* v 1.02 */
put_bits(p, 8, 0); /* units type: 0 - aspect ratio */
put_bits(p, 16, s->avctx->sample_aspect_ratio.num);
put_bits(p, 16, s->avctx->sample_aspect_ratio.den);
put_bits(p, 8, 0); /* thumbnail width */
put_bits(p, 8, 0); /* thumbnail height */
}
/* comment */
if(!(s->flags & CODEC_FLAG_BITEXACT)){
put_marker(p, COM);
flush_put_bits(p);
ptr = pbBufPtr(p);
put_bits(p, 16, 0); /* patched later */
ff_put_string(p, LIBAVCODEC_IDENT, 1);
size = strlen(LIBAVCODEC_IDENT)+3;
AV_WB16(ptr, size);
}
if( s->avctx->pix_fmt == PIX_FMT_YUV420P
||s->avctx->pix_fmt == PIX_FMT_YUV422P
||s->avctx->pix_fmt == PIX_FMT_YUV444P){
put_marker(p, COM);
flush_put_bits(p);
ptr = pbBufPtr(p);
put_bits(p, 16, 0); /* patched later */
ff_put_string(p, "CS=ITU601", 1);
size = strlen("CS=ITU601")+3;
AV_WB16(ptr, size);
}
}
void ff_mjpeg_encode_picture_header(MpegEncContext *s)
{
const int lossless= s->avctx->codec_id != CODEC_ID_MJPEG;
put_marker(&s->pb, SOI);
jpeg_put_comments(s);
jpeg_table_header(s);
switch(s->avctx->codec_id){
case CODEC_ID_MJPEG: put_marker(&s->pb, SOF0 ); break;
case CODEC_ID_LJPEG: put_marker(&s->pb, SOF3 ); break;
default: assert(0);
}
put_bits(&s->pb, 16, 17);
if(lossless && s->avctx->pix_fmt == PIX_FMT_RGB32)
put_bits(&s->pb, 8, 9); /* 9 bits/component RCT */
else
put_bits(&s->pb, 8, 8); /* 8 bits/component */
put_bits(&s->pb, 16, s->height);
put_bits(&s->pb, 16, s->width);
put_bits(&s->pb, 8, 3); /* 3 components */
/* Y component */
put_bits(&s->pb, 8, 1); /* component number */
put_bits(&s->pb, 4, s->mjpeg_hsample[0]); /* H factor */
put_bits(&s->pb, 4, s->mjpeg_vsample[0]); /* V factor */
put_bits(&s->pb, 8, 0); /* select matrix */
/* Cb component */
put_bits(&s->pb, 8, 2); /* component number */
put_bits(&s->pb, 4, s->mjpeg_hsample[1]); /* H factor */
put_bits(&s->pb, 4, s->mjpeg_vsample[1]); /* V factor */
#ifdef TWOMATRIXES
put_bits(&s->pb, 8, lossless ? 0 : 1); /* select matrix */
#else
put_bits(&s->pb, 8, 0); /* select matrix */
#endif
/* Cr component */
put_bits(&s->pb, 8, 3); /* component number */
put_bits(&s->pb, 4, s->mjpeg_hsample[2]); /* H factor */
put_bits(&s->pb, 4, s->mjpeg_vsample[2]); /* V factor */
#ifdef TWOMATRIXES
put_bits(&s->pb, 8, lossless ? 0 : 1); /* select matrix */
#else
put_bits(&s->pb, 8, 0); /* select matrix */
#endif
/* scan header */
put_marker(&s->pb, SOS);
put_bits(&s->pb, 16, 12); /* length */
put_bits(&s->pb, 8, 3); /* 3 components */
/* Y component */
put_bits(&s->pb, 8, 1); /* index */
put_bits(&s->pb, 4, 0); /* DC huffman table index */
put_bits(&s->pb, 4, 0); /* AC huffman table index */
/* Cb component */
put_bits(&s->pb, 8, 2); /* index */
put_bits(&s->pb, 4, 1); /* DC huffman table index */
put_bits(&s->pb, 4, lossless ? 0 : 1); /* AC huffman table index */
/* Cr component */
put_bits(&s->pb, 8, 3); /* index */
put_bits(&s->pb, 4, 1); /* DC huffman table index */
put_bits(&s->pb, 4, lossless ? 0 : 1); /* AC huffman table index */
put_bits(&s->pb, 8, lossless ? s->avctx->prediction_method+1 : 0); /* Ss (not used) */
switch(s->avctx->codec_id){
case CODEC_ID_MJPEG: put_bits(&s->pb, 8, 63); break; /* Se (not used) */
case CODEC_ID_LJPEG: put_bits(&s->pb, 8, 0); break; /* not used */
default: assert(0);
}
put_bits(&s->pb, 8, 0); /* Ah/Al (not used) */
}
static void escape_FF(MpegEncContext *s, int start)
{
int size= put_bits_count(&s->pb) - start*8;
int i, ff_count;
uint8_t *buf= s->pb.buf + start;
int align= (-(size_t)(buf))&3;
assert((size&7) == 0);
size >>= 3;
ff_count=0;
for(i=0; i<size && i<align; i++){
if(buf[i]==0xFF) ff_count++;
}
for(; i<size-15; i+=16){
int acc, v;
v= *(uint32_t*)(&buf[i]);
acc= (((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010;
v= *(uint32_t*)(&buf[i+4]);
acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010;
v= *(uint32_t*)(&buf[i+8]);
acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010;
v= *(uint32_t*)(&buf[i+12]);
acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010;
acc>>=4;
acc+= (acc>>16);
acc+= (acc>>8);
ff_count+= acc&0xFF;
}
for(; i<size; i++){
if(buf[i]==0xFF) ff_count++;
}
if(ff_count==0) return;
/* skip put bits */
for(i=0; i<ff_count-3; i+=4)
put_bits(&s->pb, 32, 0);
put_bits(&s->pb, (ff_count-i)*8, 0);
flush_put_bits(&s->pb);
for(i=size-1; ff_count; i--){
int v= buf[i];
if(v==0xFF){
//printf("%d %d\n", i, ff_count);
buf[i+ff_count]= 0;
ff_count--;
}
buf[i+ff_count]= v;
}
}
void ff_mjpeg_encode_stuffing(PutBitContext * pbc)
{
int length;
length= (-put_bits_count(pbc))&7;
if(length) put_bits(pbc, length, (1<<length)-1);
}
void ff_mjpeg_encode_picture_trailer(MpegEncContext *s)
{
ff_mjpeg_encode_stuffing(&s->pb);
flush_put_bits(&s->pb);
assert((s->header_bits&7)==0);
escape_FF(s, s->header_bits>>3);
put_marker(&s->pb, EOI);
}
void ff_mjpeg_encode_dc(MpegEncContext *s, int val,
uint8_t *huff_size, uint16_t *huff_code)
{
int mant, nbits;
if (val == 0) {
put_bits(&s->pb, huff_size[0], huff_code[0]);
} else {
mant = val;
if (val < 0) {
val = -val;
mant--;
}
nbits= av_log2_16bit(val) + 1;
put_bits(&s->pb, huff_size[nbits], huff_code[nbits]);
put_sbits(&s->pb, nbits, mant);
}
}
static void encode_block(MpegEncContext *s, DCTELEM *block, int n)
{
int mant, nbits, code, i, j;
int component, dc, run, last_index, val;
MJpegContext *m = s->mjpeg_ctx;
uint8_t *huff_size_ac;
uint16_t *huff_code_ac;
/* DC coef */
component = (n <= 3 ? 0 : (n&1) + 1);
dc = block[0]; /* overflow is impossible */
val = dc - s->last_dc[component];
if (n < 4) {
ff_mjpeg_encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance);
huff_size_ac = m->huff_size_ac_luminance;
huff_code_ac = m->huff_code_ac_luminance;
} else {
ff_mjpeg_encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
huff_size_ac = m->huff_size_ac_chrominance;
huff_code_ac = m->huff_code_ac_chrominance;
}
s->last_dc[component] = dc;
/* AC coefs */
run = 0;
last_index = s->block_last_index[n];
for(i=1;i<=last_index;i++) {
j = s->intra_scantable.permutated[i];
val = block[j];
if (val == 0) {
run++;
} else {
while (run >= 16) {
put_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]);
run -= 16;
}
mant = val;
if (val < 0) {
val = -val;
mant--;
}
nbits= av_log2(val) + 1;
code = (run << 4) | nbits;
put_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]);
put_sbits(&s->pb, nbits, mant);
run = 0;
}
}
/* output EOB only if not already 64 values */
if (last_index < 63 || run != 0)
put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
}
void ff_mjpeg_encode_mb(MpegEncContext *s, DCTELEM block[6][64])
{
int i;
for(i=0;i<5;i++) {
encode_block(s, block[i], i);
}
if (s->chroma_format == CHROMA_420) {
encode_block(s, block[5], 5);
} else {
encode_block(s, block[6], 6);
encode_block(s, block[5], 5);
encode_block(s, block[7], 7);
}
}
AVCodec mjpeg_encoder = {
"mjpeg",
CODEC_TYPE_VIDEO,
CODEC_ID_MJPEG,
sizeof(MpegEncContext),
MPV_encode_init,
MPV_encode_picture,
MPV_encode_end,
.pix_fmts= (enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"),
};
@@ -0,0 +1,60 @@
/*
* MJPEG encoder
* Copyright (c) 2000, 2001 Fabrice Bellard.
* Copyright (c) 2003 Alex Beregszaszi
* Copyright (c) 2003-2004 Michael Niedermayer
*
* Support for external huffman table, various fixes (AVID workaround),
* aspecting, new decode_frame mechanism and apple mjpeg-b support
* by Alex Beregszaszi
*
* 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 mjpegenc.h
* MJPEG encoder.
*/
#ifndef FFMPEG_MJPEGENC_H
#define FFMPEG_MJPEGENC_H
#include "dsputil.h"
#include "mpegvideo.h"
typedef struct MJpegContext {
uint8_t huff_size_dc_luminance[12]; //FIXME use array [3] instead of lumi / chrom, for easier addressing
uint16_t huff_code_dc_luminance[12];
uint8_t huff_size_dc_chrominance[12];
uint16_t huff_code_dc_chrominance[12];
uint8_t huff_size_ac_luminance[256];
uint16_t huff_code_ac_luminance[256];
uint8_t huff_size_ac_chrominance[256];
uint16_t huff_code_ac_chrominance[256];
} MJpegContext;
int ff_mjpeg_encode_init(MpegEncContext *s);
void ff_mjpeg_encode_close(MpegEncContext *s);
void ff_mjpeg_encode_picture_header(MpegEncContext *s);
void ff_mjpeg_encode_picture_trailer(MpegEncContext *s);
void ff_mjpeg_encode_stuffing(PutBitContext *pbc);
void ff_mjpeg_encode_dc(MpegEncContext *s, int val,
uint8_t *huff_size, uint16_t *huff_code);
void ff_mjpeg_encode_mb(MpegEncContext *s, DCTELEM block[6][64]);
#endif /* FFMPEG_MJPEGENC_H */
@@ -0,0 +1,119 @@
/*
* MLP codec common code
* Copyright (c) 2007-2008 Ian Caulfield
*
* 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 <stdint.h>
#include "libavutil/crc.h"
#include "mlp.h"
const uint8_t ff_mlp_huffman_tables[3][18][2] = {
{ /* Huffman table 0, -7 - +10 */
{0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3},
{0x04, 3}, {0x05, 3}, {0x06, 3}, {0x07, 3},
{0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9},
}, { /* Huffman table 1, -7 - +8 */
{0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3},
{0x02, 2}, {0x03, 2},
{0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9},
}, { /* Huffman table 2, -7 - +7 */
{0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3},
{0x01, 1},
{0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9},
}
};
static int crc_init = 0;
static AVCRC crc_63[1024];
static AVCRC crc_1D[1024];
static int crc_init_2D = 0;
static AVCRC crc_2D[1024];
int av_cold ff_mlp_init_crc2D(AVCodecParserContext *s)
{
if (!crc_init_2D) {
av_crc_init(crc_2D, 0, 16, 0x002D, sizeof(crc_2D));
crc_init_2D = 1;
}
return 0;
}
void av_cold ff_mlp_init_crc()
{
if (!crc_init) {
av_crc_init(crc_63, 0, 8, 0x63, sizeof(crc_63));
av_crc_init(crc_1D, 0, 8, 0x1D, sizeof(crc_1D));
crc_init = 1;
}
}
uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size)
{
uint16_t crc;
crc = av_crc(crc_2D, 0, buf, buf_size - 2);
crc ^= AV_RL16(buf + buf_size - 2);
return crc;
}
uint8_t ff_mlp_checksum8(const uint8_t *buf, unsigned int buf_size)
{
uint8_t checksum = av_crc(crc_63, 0x3c, buf, buf_size - 1); // crc_63[0xa2] == 0x3c
checksum ^= buf[buf_size-1];
return checksum;
}
uint8_t ff_mlp_restart_checksum(const uint8_t *buf, unsigned int bit_size)
{
int i;
int num_bytes = (bit_size + 2) / 8;
int crc = crc_1D[buf[0] & 0x3f];
crc = av_crc(crc_1D, crc, buf + 1, num_bytes - 2);
crc ^= buf[num_bytes - 1];
for (i = 0; i < ((bit_size + 2) & 7); i++) {
crc <<= 1;
if (crc & 0x100)
crc ^= 0x11D;
crc ^= (buf[num_bytes] >> (7 - i)) & 1;
}
return crc;
}
uint8_t ff_mlp_calculate_parity(const uint8_t *buf, unsigned int buf_size)
{
uint32_t scratch = 0;
const uint8_t *buf_end = buf + buf_size;
for (; buf < buf_end - 3; buf += 4)
scratch ^= *((const uint32_t*)buf);
scratch = xor_32_to_8(scratch);
for (; buf < buf_end; buf++)
scratch ^= *buf;
return scratch;
}
@@ -0,0 +1,121 @@
/*
* MLP codec common header file
* Copyright (c) 2007-2008 Ian Caulfield
*
* 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_MLP_H
#define FFMPEG_MLP_H
#include <stdint.h>
#include "avcodec.h"
/** Maximum number of channels that can be decoded. */
#define MAX_CHANNELS 16
/** Maximum number of matrices used in decoding; most streams have one matrix
* per output channel, but some rematrix a channel (usually 0) more than once.
*/
#define MAX_MATRICES 15
/** Maximum number of substreams that can be decoded. This could also be set
* higher, but I haven't seen any examples with more than two.
*/
#define MAX_SUBSTREAMS 2
/** maximum sample frequency seen in files */
#define MAX_SAMPLERATE 192000
/** maximum number of audio samples within one access unit */
#define MAX_BLOCKSIZE (40 * (MAX_SAMPLERATE / 48000))
/** next power of two greater than MAX_BLOCKSIZE */
#define MAX_BLOCKSIZE_POW2 (64 * (MAX_SAMPLERATE / 48000))
/** number of allowed filters */
#define NUM_FILTERS 2
/** The maximum number of taps in either the IIR or FIR filter;
* I believe MLP actually specifies the maximum order for IIR filters as four,
* and that the sum of the orders of both filters must be <= 8.
*/
#define MAX_FILTER_ORDER 8
/** Code that signals end of a stream. */
#define END_OF_STREAM 0xd234d234
#define FIR 0
#define IIR 1
/** filter data */
typedef struct {
uint8_t order; ///< number of taps in filter
uint8_t shift; ///< Right shift to apply to output of filter.
int32_t coeff[MAX_FILTER_ORDER];
int32_t state[MAX_FILTER_ORDER];
} FilterParams;
/** sample data coding information */
typedef struct {
FilterParams filter_params[NUM_FILTERS];
int16_t huff_offset; ///< Offset to apply to residual values.
int32_t sign_huff_offset; ///< sign/rounding-corrected version of huff_offset
uint8_t codebook; ///< Which VLC codebook to use to read residuals.
uint8_t huff_lsbs; ///< Size of residual suffix not encoded using VLC.
} ChannelParams;
/** Tables defining the Huffman codes.
* There are three entropy coding methods used in MLP (four if you count
* "none" as a method). These use the same sequences for codes starting with
* 00 or 01, but have different codes starting with 1.
*/
extern const uint8_t ff_mlp_huffman_tables[3][18][2];
/** MLP uses checksums that seem to be based on the standard CRC algorithm, but
* are not (in implementation terms, the table lookup and XOR are reversed).
* We can implement this behavior using a standard av_crc on all but the
* last element, then XOR that with the last element.
*/
uint8_t ff_mlp_checksum8 (const uint8_t *buf, unsigned int buf_size);
uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size);
/** Calculate an 8-bit checksum over a restart header -- a non-multiple-of-8
* number of bits, starting two bits into the first byte of buf.
*/
uint8_t ff_mlp_restart_checksum(const uint8_t *buf, unsigned int bit_size);
/** XOR together all the bytes of a buffer.
* Does this belong in dspcontext?
*/
uint8_t ff_mlp_calculate_parity(const uint8_t *buf, unsigned int buf_size);
int ff_mlp_init_crc2D(AVCodecParserContext *s);
void ff_mlp_init_crc();
/** XOR four bytes into one. */
static inline uint8_t xor_32_to_8(uint32_t value)
{
value ^= value >> 16;
value ^= value >> 8;
return value;
}
#endif /* FFMPEG_MLP_H */
@@ -0,0 +1,289 @@
/*
* MLP parser
* Copyright (c) 2007 Ian Caulfield
*
* 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 mlp_parser.c
* MLP parser
*/
#include <stdint.h>
#include "libavutil/crc.h"
#include "bitstream.h"
#include "parser.h"
#include "mlp_parser.h"
#include "mlp.h"
static const uint8_t mlp_quants[16] = {
16, 20, 24, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static const uint8_t mlp_channels[32] = {
1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static const uint8_t thd_chancount[13] = {
// LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2
2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
};
static int mlp_samplerate(int in)
{
if (in == 0xF)
return 0;
return (in & 8 ? 44100 : 48000) << (in & 7) ;
}
static int truehd_channels(int chanmap)
{
int channels = 0, i;
for (i = 0; i < 13; i++)
channels += thd_chancount[i] * ((chanmap >> i) & 1);
return channels;
}
/** Read a major sync info header - contains high level information about
* the stream - sample rate, channel arrangement etc. Most of this
* information is not actually necessary for decoding, only for playback.
* gb must be a freshly initialized GetBitContext with no bits read.
*/
int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb)
{
int ratebits;
uint16_t checksum;
assert(get_bits_count(gb) == 0);
if (gb->size_in_bits < 28 << 3) {
av_log(log, AV_LOG_ERROR, "packet too short, unable to read major sync\n");
return -1;
}
checksum = ff_mlp_checksum16(gb->buffer, 26);
if (checksum != AV_RL16(gb->buffer+26)) {
av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n");
return -1;
}
if (get_bits_long(gb, 24) != 0xf8726f) /* Sync words */
return -1;
mh->stream_type = get_bits(gb, 8);
if (mh->stream_type == 0xbb) {
mh->group1_bits = mlp_quants[get_bits(gb, 4)];
mh->group2_bits = mlp_quants[get_bits(gb, 4)];
ratebits = get_bits(gb, 4);
mh->group1_samplerate = mlp_samplerate(ratebits);
mh->group2_samplerate = mlp_samplerate(get_bits(gb, 4));
skip_bits(gb, 11);
mh->channels_mlp = get_bits(gb, 5);
} else if (mh->stream_type == 0xba) {
mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere?
mh->group2_bits = 0;
ratebits = get_bits(gb, 4);
mh->group1_samplerate = mlp_samplerate(ratebits);
mh->group2_samplerate = 0;
skip_bits(gb, 8);
mh->channels_thd_stream1 = get_bits(gb, 5);
skip_bits(gb, 2);
mh->channels_thd_stream2 = get_bits(gb, 13);
} else
return -1;
mh->access_unit_size = 40 << (ratebits & 7);
mh->access_unit_size_pow2 = 64 << (ratebits & 7);
skip_bits_long(gb, 48);
mh->is_vbr = get_bits1(gb);
mh->peak_bitrate = (get_bits(gb, 15) * mh->group1_samplerate + 8) >> 4;
mh->num_substreams = get_bits(gb, 4);
skip_bits_long(gb, 4 + 11 * 8);
return 0;
}
typedef struct MLPParseContext
{
ParseContext pc;
int bytes_left;
int in_sync;
int num_substreams;
} MLPParseContext;
static int mlp_parse(AVCodecParserContext *s,
AVCodecContext *avctx,
const uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size)
{
MLPParseContext *mp = s->priv_data;
int sync_present;
uint8_t parity_bits;
int next;
int i, p = 0;
*poutbuf_size = 0;
if (buf_size == 0)
return 0;
if (!mp->in_sync) {
// Not in sync - find a major sync header
for (i = 0; i < buf_size; i++) {
mp->pc.state = (mp->pc.state << 8) | buf[i];
if ((mp->pc.state & 0xfffffffe) == 0xf8726fba) {
mp->in_sync = 1;
mp->bytes_left = 0;
break;
}
}
if (!mp->in_sync) {
ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
return buf_size;
}
ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size);
return i - 7;
}
if (mp->bytes_left == 0) {
// Find length of this packet
/* Copy overread bytes from last frame into buffer. */
for(; mp->pc.overread>0; mp->pc.overread--) {
mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++];
}
if (mp->pc.index + buf_size < 2) {
ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
return buf_size;
}
mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8)
| (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]);
mp->bytes_left = (mp->bytes_left & 0xfff) * 2;
mp->bytes_left -= mp->pc.index;
}
next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left;
if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) {
mp->bytes_left -= buf_size;
return buf_size;
}
mp->bytes_left = 0;
sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba;
if (!sync_present) {
/* The first nibble of a frame is a parity check of the 4-byte
* access unit header and all the 2- or 4-byte substream headers. */
// Only check when this isn't a sync frame - syncs have a checksum.
parity_bits = 0;
for (i = -1; i < mp->num_substreams; i++) {
parity_bits ^= buf[p++];
parity_bits ^= buf[p++];
if (i < 0 || buf[p-2] & 0x80) {
parity_bits ^= buf[p++];
parity_bits ^= buf[p++];
}
}
if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) {
av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n");
goto lost_sync;
}
} else {
GetBitContext gb;
MLPHeaderInfo mh;
init_get_bits(&gb, buf + 4, (buf_size - 4) << 3);
if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0)
goto lost_sync;
#ifdef CONFIG_AUDIO_NONSHORT
avctx->bits_per_sample = mh.group1_bits;
if (avctx->bits_per_sample > 16)
avctx->sample_fmt = SAMPLE_FMT_S32;
#endif
avctx->sample_rate = mh.group1_samplerate;
avctx->frame_size = mh.access_unit_size;
if (mh.stream_type == 0xbb) {
/* MLP stream */
avctx->channels = mlp_channels[mh.channels_mlp];
} else { /* mh.stream_type == 0xba */
/* TrueHD stream */
if (mh.channels_thd_stream2)
avctx->channels = truehd_channels(mh.channels_thd_stream2);
else
avctx->channels = truehd_channels(mh.channels_thd_stream1);
}
if (!mh.is_vbr) /* Stream is CBR */
avctx->bit_rate = mh.peak_bitrate;
mp->num_substreams = mh.num_substreams;
}
*poutbuf = buf;
*poutbuf_size = buf_size;
return next;
lost_sync:
mp->in_sync = 0;
return 1;
}
AVCodecParser mlp_parser = {
{ CODEC_ID_MLP },
sizeof(MLPParseContext),
ff_mlp_init_crc2D,
mlp_parse,
NULL,
};
@@ -0,0 +1,59 @@
/*
* MLP parser prototypes
* Copyright (c) 2007 Ian Caulfield
*
* 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 mlp_parser.h
* MLP parser prototypes
*/
#ifndef FFMPEG_MLP_PARSER_H
#define FFMPEG_MLP_PARSER_H
#include "bitstream.h"
typedef struct MLPHeaderInfo
{
int stream_type; ///< 0xBB for MLP, 0xBA for TrueHD
int group1_bits; ///< The bit depth of the first substream
int group2_bits; ///< Bit depth of the second substream (MLP only)
int group1_samplerate; ///< Sample rate of first substream
int group2_samplerate; ///< Sample rate of second substream (MLP only)
int channels_mlp; ///< Channel arrangement for MLP streams
int channels_thd_stream1; ///< Channel arrangement for substream 1 of TrueHD streams (5.1)
int channels_thd_stream2; ///< Channel arrangement for substream 2 of TrueHD streams (7.1)
int access_unit_size; ///< Number of samples per coded frame
int access_unit_size_pow2; ///< Next power of two above number of samples per frame
int is_vbr; ///< Stream is VBR instead of CBR
int peak_bitrate; ///< Peak bitrate for VBR, actual bitrate (==peak) for CBR
int num_substreams; ///< Number of substreams within stream
} MLPHeaderInfo;
int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb);
#endif /* FFMPEG_MLP_PARSER_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,212 @@
/*
* American Laser Games MM Video Decoder
* Copyright (c) 2006,2008 Peter Ross
*
* 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 mm.c
* American Laser Games MM Video Decoder
* by Peter Ross (suxen_drol at hotmail dot com)
*
* The MM format was used by IBM-PC ports of ALG's "arcade shooter" games,
* including Mad Dog McCree and Crime Patrol.
*
* Technical details here:
* http://wiki.multimedia.cx/index.php?title=American_Laser_Games_MM
*/
#include "avcodec.h"
#define MM_PREAMBLE_SIZE 6
#define MM_TYPE_INTER 0x5
#define MM_TYPE_INTRA 0x8
#define MM_TYPE_INTRA_HH 0xc
#define MM_TYPE_INTER_HH 0xd
#define MM_TYPE_INTRA_HHV 0xe
#define MM_TYPE_INTER_HHV 0xf
#define MM_TYPE_PALETTE 0x31
typedef struct MmContext {
AVCodecContext *avctx;
AVFrame frame;
int palette[AVPALETTE_COUNT];
} MmContext;
static av_cold int mm_decode_init(AVCodecContext *avctx)
{
MmContext *s = avctx->priv_data;
s->avctx = avctx;
avctx->pix_fmt = PIX_FMT_PAL8;
if (avcodec_check_dimensions(avctx, avctx->width, avctx->height))
return -1;
s->frame.reference = 1;
if (avctx->get_buffer(avctx, &s->frame)) {
av_log(s->avctx, AV_LOG_ERROR, "mmvideo: get_buffer() failed\n");
return -1;
}
return 0;
}
static void mm_decode_pal(MmContext *s, const uint8_t *buf, const uint8_t *buf_end)
{
int i;
buf += 4;
for (i=0; i<128 && buf+2<buf_end; i++) {
s->palette[i] = AV_RB24(buf);
s->palette[i+128] = s->palette[i]<<2;
buf += 3;
}
}
static void mm_decode_intra(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)
{
int i, x, y;
i=0; x=0; y=0;
while(i<buf_size) {
int run_length, color;
if (buf[i] & 0x80) {
run_length = 1;
color = buf[i];
i++;
}else{
run_length = (buf[i] & 0x7f) + 2;
color = buf[i+1];
i+=2;
}
if (half_horiz)
run_length *=2;
if (color) {
memset(s->frame.data[0] + y*s->frame.linesize[0] + x, color, run_length);
if (half_vert)
memset(s->frame.data[0] + (y+1)*s->frame.linesize[0] + x, color, run_length);
}
x+= run_length;
if (x >= s->avctx->width) {
x=0;
y += half_vert ? 2 : 1;
}
}
}
static void mm_decode_inter(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)
{
const int data_ptr = 2 + AV_RL16(&buf[0]);
int d, r, y;
d = data_ptr; r = 2; y = 0;
while(r < data_ptr) {
int i, j;
int length = buf[r] & 0x7f;
int x = buf[r+1] + ((buf[r] & 0x80) << 1);
r += 2;
if (length==0) {
y += x;
continue;
}
for(i=0; i<length; i++) {
for(j=0; j<8; j++) {
int replace = (buf[r+i] >> (7-j)) & 1;
if (replace) {
int color = buf[d];
s->frame.data[0][y*s->frame.linesize[0] + x] = color;
if (half_horiz)
s->frame.data[0][y*s->frame.linesize[0] + x + 1] = color;
if (half_vert) {
s->frame.data[0][(y+1)*s->frame.linesize[0] + x] = color;
if (half_horiz)
s->frame.data[0][(y+1)*s->frame.linesize[0] + x + 1] = color;
}
d++;
}
x += half_horiz ? 2 : 1;
}
}
r += length;
y += half_vert ? 2 : 1;
}
}
static int mm_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
MmContext *s = avctx->priv_data;
const uint8_t *buf_end = buf+buf_size;
int type;
type = AV_RL16(&buf[0]);
buf += MM_PREAMBLE_SIZE;
buf_size -= MM_PREAMBLE_SIZE;
switch(type) {
case MM_TYPE_PALETTE : mm_decode_pal(s, buf, buf_end); return buf_size;
case MM_TYPE_INTRA : mm_decode_intra(s, 0, 0, buf, buf_size); break;
case MM_TYPE_INTRA_HH : mm_decode_intra(s, 1, 0, buf, buf_size); break;
case MM_TYPE_INTRA_HHV : mm_decode_intra(s, 1, 1, buf, buf_size); break;
case MM_TYPE_INTER : mm_decode_inter(s, 0, 0, buf, buf_size); break;
case MM_TYPE_INTER_HH : mm_decode_inter(s, 1, 0, buf, buf_size); break;
case MM_TYPE_INTER_HHV : mm_decode_inter(s, 1, 1, buf, buf_size); break;
default :
return -1;
}
memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
*data_size = sizeof(AVFrame);
*(AVFrame*)data = s->frame;
return buf_size;
}
static av_cold int mm_decode_end(AVCodecContext *avctx)
{
MmContext *s = avctx->priv_data;
if(s->frame.data[0])
avctx->release_buffer(avctx, &s->frame);
return 0;
}
AVCodec mmvideo_decoder = {
"mmvideo",
CODEC_TYPE_VIDEO,
CODEC_ID_MMVIDEO,
sizeof(MmContext),
mm_decode_init,
NULL,
mm_decode_end,
mm_decode_frame,
CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM Video"),
};
@@ -0,0 +1,164 @@
/*
* (c) 2001 Fabrice Bellard
*
* 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 motion_test.c
* motion test.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include "dsputil.h"
#include "i386/mmx.h"
#undef exit
#undef printf
#undef random
#define WIDTH 64
#define HEIGHT 64
uint8_t img1[WIDTH * HEIGHT];
uint8_t img2[WIDTH * HEIGHT];
void fill_random(uint8_t *tab, int size)
{
int i;
for(i=0;i<size;i++) {
#if 1
tab[i] = random() % 256;
#else
tab[i] = i;
#endif
}
}
void help(void)
{
printf("motion-test [-h]\n"
"test motion implementations\n");
exit(1);
}
int64_t gettime(void)
{
struct timeval tv;
gettimeofday(&tv,NULL);
return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
}
#define NB_ITS 500
int dummy;
void test_motion(const char *name,
me_cmp_func test_func, me_cmp_func ref_func)
{
int x, y, d1, d2, it;
uint8_t *ptr;
int64_t ti;
printf("testing '%s'\n", name);
/* test correctness */
for(it=0;it<20;it++) {
fill_random(img1, WIDTH * HEIGHT);
fill_random(img2, WIDTH * HEIGHT);
for(y=0;y<HEIGHT-17;y++) {
for(x=0;x<WIDTH-17;x++) {
ptr = img2 + y * WIDTH + x;
d1 = test_func(NULL, img1, ptr, WIDTH, 1);
d2 = ref_func(NULL, img1, ptr, WIDTH, 1);
if (d1 != d2) {
printf("error: mmx=%d c=%d\n", d1, d2);
}
}
}
}
emms_c();
/* speed test */
ti = gettime();
d1 = 0;
for(it=0;it<NB_ITS;it++) {
for(y=0;y<HEIGHT-17;y++) {
for(x=0;x<WIDTH-17;x++) {
ptr = img2 + y * WIDTH + x;
d1 += test_func(NULL, img1, ptr, WIDTH, 1);
}
}
}
emms_c();
dummy = d1; /* avoid optimization */
ti = gettime() - ti;
printf(" %0.0f kop/s\n",
(double)NB_ITS * (WIDTH - 16) * (HEIGHT - 16) /
(double)(ti / 1000.0));
}
int main(int argc, char **argv)
{
AVCodecContext *ctx;
int c;
DSPContext cctx, mmxctx;
int flags[2] = { FF_MM_MMX, FF_MM_MMXEXT };
for(;;) {
c = getopt(argc, argv, "h");
if (c == -1)
break;
switch(c) {
case 'h':
help();
break;
}
}
printf("ffmpeg motion test\n");
ctx = avcodec_alloc_context();
ctx->dsp_mask = FF_MM_FORCE;
dsputil_init(&cctx, ctx);
for (c = 0; c < 2; c++) {
int x;
ctx->dsp_mask = FF_MM_FORCE | flags[c];
dsputil_init(&mmxctx, ctx);
for (x = 0; x < 2; x++) {
printf("%s for %dx%d pixels\n", c ? "mmx2" : "mmx",
x ? 8 : 16, x ? 8 : 16);
test_motion("mmx", mmxctx.pix_abs[x][0], cctx.pix_abs[x][0]);
test_motion("mmx_x2", mmxctx.pix_abs[x][1], cctx.pix_abs[x][1]);
test_motion("mmx_y2", mmxctx.pix_abs[x][2], cctx.pix_abs[x][2]);
test_motion("mmx_xy2", mmxctx.pix_abs[x][3], cctx.pix_abs[x][3]);
}
}
av_free(ctx);
return 0;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,363 @@
/*
* Motion Pixels Video Decoder
* Copyright (c) 2008 Gregory Montoir (cyx@users.sourceforge.net)
*
* 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 "bitstream.h"
#include "dsputil.h"
#define MAX_HUFF_CODES 16
typedef struct YuvPixel {
int8_t y, v, u;
} YuvPixel;
typedef struct HuffCode {
int code;
uint8_t size;
uint8_t delta;
} HuffCode;
typedef struct MotionPixelsContext {
AVCodecContext *avctx;
AVFrame frame;
DSPContext dsp;
uint8_t *changes_map;
int offset_bits_len;
int codes_count, current_codes_count;
int max_codes_bits;
HuffCode codes[MAX_HUFF_CODES];
VLC vlc;
YuvPixel *vpt, *hpt;
uint8_t gradient_scale[3];
uint8_t *bswapbuf;
int bswapbuf_size;
} MotionPixelsContext;
static YuvPixel mp_rgb_yuv_table[1 << 15];
static int mp_yuv_to_rgb(int y, int v, int u, int clip_rgb) {
static const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
int r, g, b;
r = (1000 * y + 701 * v) / 1000;
g = (1000 * y - 357 * v - 172 * u) / 1000;
b = (1000 * y + 886 * u) / 1000;
if (clip_rgb)
return ((cm[r * 8] & 0xF8) << 7) | ((cm[g * 8] & 0xF8) << 2) | (cm[b * 8] >> 3);
if ((unsigned)r < 32 && (unsigned)g < 32 && (unsigned)b < 32)
return (r << 10) | (g << 5) | b;
return 1 << 15;
}
static void mp_set_zero_yuv(YuvPixel *p)
{
int i, j;
for (i = 0; i < 31; ++i) {
for (j = 31; j > i; --j)
if (!(p[j].u | p[j].v | p[j].y))
p[j] = p[j - 1];
for (j = 0; j < 31 - i; ++j)
if (!(p[j].u | p[j].v | p[j].y))
p[j] = p[j + 1];
}
}
static void mp_build_rgb_yuv_table(YuvPixel *p)
{
int y, v, u, i;
for (y = 0; y <= 31; ++y)
for (v = -31; v <= 31; ++v)
for (u = -31; u <= 31; ++u) {
i = mp_yuv_to_rgb(y, v, u, 0);
if (i < (1 << 15) && !(p[i].u | p[i].v | p[i].y)) {
p[i].y = y;
p[i].v = v;
p[i].u = u;
}
}
for (i = 0; i < 1024; ++i)
mp_set_zero_yuv(p + i * 32);
}
static av_cold int mp_decode_init(AVCodecContext *avctx)
{
MotionPixelsContext *mp = avctx->priv_data;
if (!mp_rgb_yuv_table[0].u) {
mp_build_rgb_yuv_table(mp_rgb_yuv_table);
}
mp->avctx = avctx;
dsputil_init(&mp->dsp, avctx);
mp->changes_map = av_mallocz(avctx->width * avctx->height);
mp->offset_bits_len = av_log2(avctx->width * avctx->height) + 1;
mp->vpt = av_mallocz(avctx->height * sizeof(YuvPixel));
mp->hpt = av_mallocz(avctx->height * avctx->width / 16 * sizeof(YuvPixel));
return 0;
}
static void mp_read_changes_map(MotionPixelsContext *mp, GetBitContext *gb, int count, int bits_len, int read_color)
{
uint16_t *pixels;
int offset, w, h, color = 0, x, y, i;
while (count--) {
offset = get_bits_long(gb, mp->offset_bits_len);
w = get_bits(gb, bits_len) + 1;
h = get_bits(gb, bits_len) + 1;
if (read_color)
color = get_bits(gb, 15);
x = offset % mp->avctx->width;
y = offset / mp->avctx->width;
if (y >= mp->avctx->height)
continue;
w = FFMIN(w, mp->avctx->width - x);
h = FFMIN(h, mp->avctx->height - y);
pixels = (uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
while (h--) {
mp->changes_map[offset] = w;
if (read_color)
for (i = 0; i < w; ++i)
pixels[i] = color;
offset += mp->avctx->width;
pixels += mp->frame.linesize[0] / 2;
}
}
}
static void mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size, int code)
{
while (get_bits1(gb)) {
++size;
if (size > mp->max_codes_bits) {
av_log(mp->avctx, AV_LOG_ERROR, "invalid code size %d/%d\n", size, mp->max_codes_bits);
return;
}
code <<= 1;
mp_get_code(mp, gb, size, code + 1);
}
if (mp->current_codes_count >= MAX_HUFF_CODES) {
av_log(mp->avctx, AV_LOG_ERROR, "too many codes\n");
return;
}
mp->codes[mp->current_codes_count ].code = code;
mp->codes[mp->current_codes_count++].size = size;
}
static void mp_read_codes_table(MotionPixelsContext *mp, GetBitContext *gb)
{
if (mp->codes_count == 1) {
mp->codes[0].delta = get_bits(gb, 4);
} else {
int i;
mp->max_codes_bits = get_bits(gb, 4);
for (i = 0; i < mp->codes_count; ++i)
mp->codes[i].delta = get_bits(gb, 4);
mp->current_codes_count = 0;
mp_get_code(mp, gb, 0, 0);
}
}
static int mp_gradient(MotionPixelsContext *mp, int component, int v)
{
int delta;
delta = (v - 7) * mp->gradient_scale[component];
mp->gradient_scale[component] = (v == 0 || v == 14) ? 2 : 1;
return delta;
}
static YuvPixel mp_get_yuv_from_rgb(MotionPixelsContext *mp, int x, int y)
{
int color;
color = *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
return mp_rgb_yuv_table[color];
}
static void mp_set_rgb_from_yuv(MotionPixelsContext *mp, int x, int y, const YuvPixel *p)
{
int color;
color = mp_yuv_to_rgb(p->y, p->v, p->u, 1);
*(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2] = color;
}
static int mp_get_vlc(MotionPixelsContext *mp, GetBitContext *gb)
{
int i;
i = (mp->codes_count == 1) ? 0 : get_vlc2(gb, mp->vlc.table, mp->max_codes_bits, 1);
return mp->codes[i].delta;
}
static void mp_decode_line(MotionPixelsContext *mp, GetBitContext *gb, int y)
{
YuvPixel p;
const int y0 = y * mp->avctx->width;
int w, i, x = 0;
p = mp->vpt[y];
if (mp->changes_map[y0 + x] == 0) {
memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
++x;
}
while (x < mp->avctx->width) {
w = mp->changes_map[y0 + x];
if (w != 0) {
if ((y & 3) == 0) {
if (mp->changes_map[y0 + x + mp->avctx->width] < w ||
mp->changes_map[y0 + x + mp->avctx->width * 2] < w ||
mp->changes_map[y0 + x + mp->avctx->width * 3] < w) {
for (i = (x + 3) & ~3; i < x + w; i += 4) {
mp->hpt[((y / 4) * mp->avctx->width + i) / 4] = mp_get_yuv_from_rgb(mp, i, y);
}
}
}
x += w;
memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
p = mp_get_yuv_from_rgb(mp, x - 1, y);
} else {
p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
if ((x & 3) == 0) {
if ((y & 3) == 0) {
p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
mp->hpt[((y / 4) * mp->avctx->width + x) / 4] = p;
} else {
p.v = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].v;
p.u = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].u;
}
}
mp_set_rgb_from_yuv(mp, x, y, &p);
++x;
}
}
}
static void mp_decode_frame_helper(MotionPixelsContext *mp, GetBitContext *gb)
{
YuvPixel p;
int y, y0;
for (y = 0; y < mp->avctx->height; ++y) {
if (mp->changes_map[y * mp->avctx->width] != 0) {
memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
p = mp_get_yuv_from_rgb(mp, 0, y);
} else {
p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
if ((y & 3) == 0) {
p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
}
mp->vpt[y] = p;
mp_set_rgb_from_yuv(mp, 0, y, &p);
}
}
for (y0 = 0; y0 < 2; ++y0)
for (y = y0; y < mp->avctx->height; y += 2)
mp_decode_line(mp, gb, y);
}
static int mp_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
MotionPixelsContext *mp = avctx->priv_data;
GetBitContext gb;
int i, count1, count2, sz;
mp->frame.reference = 1;
mp->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
if (avctx->reget_buffer(avctx, &mp->frame)) {
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
return -1;
}
/* le32 bitstream msb first */
mp->bswapbuf = av_fast_realloc(mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
mp->dsp.bswap_buf((uint32_t *)mp->bswapbuf, (const uint32_t *)buf, buf_size / 4);
if (buf_size & 3)
memcpy(mp->bswapbuf + (buf_size & ~3), buf + (buf_size & ~3), buf_size & 3);
init_get_bits(&gb, mp->bswapbuf, buf_size * 8);
memset(mp->changes_map, 0, avctx->width * avctx->height);
for (i = !(avctx->extradata[1] & 2); i < 2; ++i) {
count1 = get_bits(&gb, 12);
count2 = get_bits(&gb, 12);
mp_read_changes_map(mp, &gb, count1, 8, i);
mp_read_changes_map(mp, &gb, count2, 4, i);
}
mp->codes_count = get_bits(&gb, 4);
if (mp->codes_count == 0)
goto end;
if (mp->changes_map[0] == 0) {
*(uint16_t *)mp->frame.data[0] = get_bits(&gb, 15);
mp->changes_map[0] = 1;
}
mp_read_codes_table(mp, &gb);
sz = get_bits(&gb, 18);
if (avctx->extradata[0] != 5)
sz += get_bits(&gb, 18);
if (sz == 0)
goto end;
init_vlc(&mp->vlc, mp->max_codes_bits, mp->codes_count, &mp->codes[0].size, sizeof(HuffCode), 1, &mp->codes[0].code, sizeof(HuffCode), 4, 0);
mp_decode_frame_helper(mp, &gb);
free_vlc(&mp->vlc);
end:
*data_size = sizeof(AVFrame);
*(AVFrame *)data = mp->frame;
return buf_size;
}
static av_cold int mp_decode_end(AVCodecContext *avctx)
{
MotionPixelsContext *mp = avctx->priv_data;
av_freep(&mp->changes_map);
av_freep(&mp->vpt);
av_freep(&mp->hpt);
av_freep(&mp->bswapbuf);
if (mp->frame.data[0])
avctx->release_buffer(avctx, &mp->frame);
return 0;
}
AVCodec motionpixels_decoder = {
"motionpixels",
CODEC_TYPE_VIDEO,
CODEC_ID_MOTIONPIXELS,
sizeof(MotionPixelsContext),
mp_decode_init,
NULL,
mp_decode_end,
mp_decode_frame,
CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("Motion Pixels Video"),
};
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2008 Reimar Döffinger
*
* 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 text2movsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe){
if (buf_size > 0xffff) return 0;
*poutbuf_size = buf_size + 2;
*poutbuf = av_malloc(*poutbuf_size + FF_INPUT_BUFFER_PADDING_SIZE);
AV_WB16(*poutbuf, buf_size);
memcpy(*poutbuf + 2, buf, buf_size);
return 1;
}
AVBitStreamFilter text2movsub_bsf={
"text2movsub",
0,
text2movsub,
};
static int mov2textsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe){
if (buf_size < 2) return 0;
*poutbuf_size = FFMIN(buf_size - 2, AV_RB16(buf));
*poutbuf = av_malloc(*poutbuf_size + FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(*poutbuf, buf + 2, *poutbuf_size);
return 1;
}
AVBitStreamFilter mov2textsub_bsf={
"mov2textsub",
0,
mov2textsub,
};
@@ -0,0 +1,86 @@
/*
* 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"
#include "mpegaudio.h"
static int mp3_header_compress(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe){
uint32_t header, extraheader;
int mode_extension, header_size;
if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){
av_log(avctx, AV_LOG_ERROR, "not standards compliant\n");
return -1;
}
header = AV_RB32(buf);
mode_extension= (header>>4)&3;
if(ff_mpa_check_header(header) < 0 || (header&0x60000) != 0x20000){
output_unchanged:
*poutbuf= (uint8_t *) buf;
*poutbuf_size= buf_size;
av_log(avctx, AV_LOG_INFO, "cannot compress %08X\n", header);
return 0;
}
if(avctx->extradata_size == 0){
avctx->extradata_size=15;
avctx->extradata= av_malloc(avctx->extradata_size);
strcpy(avctx->extradata, "FFCMP3 0.0");
memcpy(avctx->extradata+11, buf, 4);
}
if(avctx->extradata_size != 15){
av_log(avctx, AV_LOG_ERROR, "Extradata invalid\n");
return -1;
}
extraheader = AV_RB32(avctx->extradata+11);
if((extraheader&MP3_MASK) != (header&MP3_MASK))
goto output_unchanged;
header_size= (header&0x10000) ? 4 : 6;
*poutbuf_size= buf_size - header_size;
*poutbuf= av_malloc(buf_size - header_size + FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(*poutbuf, buf + header_size, buf_size - header_size + FF_INPUT_BUFFER_PADDING_SIZE);
if(avctx->channels==2){
if((header & (3<<19)) != 3<<19){
(*poutbuf)[1] &= 0x3F;
(*poutbuf)[1] |= mode_extension<<6;
FFSWAP(int, (*poutbuf)[1], (*poutbuf)[2]);
}else{
(*poutbuf)[1] &= 0x8F;
(*poutbuf)[1] |= mode_extension<<4;
}
}
return 1;
}
AVBitStreamFilter mp3_header_compress_bsf={
"mp3comp",
0,
mp3_header_compress,
};
@@ -0,0 +1,96 @@
/*
* 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"
#include "mpegaudio.h"
#include "mpegaudiodata.h"
static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe){
uint32_t header;
int sample_rate= avctx->sample_rate;
int sample_rate_index=0;
int lsf, mpeg25, bitrate_index, frame_size;
header = AV_RB32(buf);
if(ff_mpa_check_header(header) >= 0){
*poutbuf= (uint8_t *) buf;
*poutbuf_size= buf_size;
return 0;
}
if(avctx->extradata_size != 15 || strcmp(avctx->extradata, "FFCMP3 0.0")){
av_log(avctx, AV_LOG_ERROR, "Extradata invalid %d\n", avctx->extradata_size);
return -1;
}
header= AV_RB32(avctx->extradata+11) & MP3_MASK;
lsf = sample_rate < (24000+32000)/2;
mpeg25 = sample_rate < (12000+16000)/2;
sample_rate_index= (header>>10)&3;
sample_rate= ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off
for(bitrate_index=2; bitrate_index<30; bitrate_index++){
frame_size = ff_mpa_bitrate_tab[lsf][2][bitrate_index>>1];
frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1);
if(frame_size == buf_size + 4)
break;
if(frame_size == buf_size + 6)
break;
}
if(bitrate_index == 30){
av_log(avctx, AV_LOG_ERROR, "Could not find bitrate_index.\n");
return -1;
}
header |= (bitrate_index&1)<<9;
header |= (bitrate_index>>1)<<12;
header |= (frame_size == buf_size + 4)<<16; //FIXME actually set a correct crc instead of 0
*poutbuf_size= frame_size;
*poutbuf= av_malloc(frame_size + FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(*poutbuf + frame_size - buf_size, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
if(avctx->channels==2){
uint8_t *p= *poutbuf + frame_size - buf_size;
if(lsf){
FFSWAP(int, p[1], p[2]);
header |= (p[1] & 0xC0)>>2;
p[1] &= 0x3F;
}else{
header |= p[1] & 0x30;
p[1] &= 0xCF;
}
}
AV_WB32(*poutbuf, header);
return 1;
}
AVBitStreamFilter mp3_header_decompress_bsf={
"mp3decomp",
0,
mp3_header_decompress,
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,65 @@
/*
* MSMPEG4 backend for ffmpeg encoder and decoder
* copyright (c) 2007 Aurelien Jacobs <aurel@gnuage.org>
*
* 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 msmpeg4.h
*/
#ifndef FFMPEG_MSMPEG4_H
#define FFMPEG_MSMPEG4_H
#include "config.h"
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
#define INTER_INTRA_VLC_BITS 3
#define MB_NON_INTRA_VLC_BITS 9
#define MB_INTRA_VLC_BITS 9
extern VLC ff_mb_non_intra_vlc[4];
extern VLC ff_inter_intra_vlc;
void ff_msmpeg4_code012(PutBitContext *pb, int n);
void ff_msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n);
void ff_msmpeg4_handle_slices(MpegEncContext *s);
void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my);
int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n,
uint8_t **coded_block_ptr);
int ff_msmpeg4_decode_motion(MpegEncContext * s, int *mx_ptr, int *my_ptr);
int ff_msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
int n, int coded, const uint8_t *scan_table);
int ff_wmv2_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
#define ENABLE_MSMPEG4_DECODER (ENABLE_MSMPEG4V1_DECODER || \
ENABLE_MSMPEG4V2_DECODER || \
ENABLE_MSMPEG4V3_DECODER || \
ENABLE_WMV2_DECODER)
#define ENABLE_MSMPEG4_ENCODER (ENABLE_MSMPEG4V1_ENCODER || \
ENABLE_MSMPEG4V2_ENCODER || \
ENABLE_MSMPEG4V3_ENCODER || \
ENABLE_WMV2_ENCODER)
#define ENABLE_MSMPEG4 (ENABLE_MSMPEG4_DECODER || ENABLE_MSMPEG4_ENCODER)
#define ENABLE_WMV2 (ENABLE_WMV2_DECODER || ENABLE_WMV2_ENCODER)
#define ENABLE_WMV_DECODER (ENABLE_WMV1_DECODER || ENABLE_WMV2_DECODER)
#define ENABLE_WMV_ENCODER (ENABLE_WMV1_ENCODER || ENABLE_WMV2_ENCODER)
#endif /* FFMPEG_MSMPEG4_H */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -2,19 +2,21 @@
* Micrsoft RLE 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
*/
/**
@@ -34,7 +36,6 @@
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "avcodec.h"
#include "dsputil.h"
@@ -42,7 +43,7 @@ typedef struct MsrleContext {
AVCodecContext *avctx;
AVFrame frame;
unsigned char *buf;
const unsigned char *buf;
int size;
} MsrleContext;
@@ -235,14 +236,13 @@ static void msrle_decode_pal8(MsrleContext *s)
stream_ptr, s->size);
}
static int msrle_decode_init(AVCodecContext *avctx)
static av_cold int msrle_decode_init(AVCodecContext *avctx)
{
MsrleContext *s = (MsrleContext *)avctx->priv_data;
MsrleContext *s = avctx->priv_data;
s->avctx = avctx;
avctx->pix_fmt = PIX_FMT_PAL8;
avctx->has_b_frames = 0;
s->frame.data[0] = NULL;
return 0;
@@ -250,13 +250,9 @@ static int msrle_decode_init(AVCodecContext *avctx)
static int msrle_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
const uint8_t *buf, int buf_size)
{
MsrleContext *s = (MsrleContext *)avctx->priv_data;
/* no supplementary picture */
if (buf_size == 0)
return 0;
MsrleContext *s = avctx->priv_data;
s->buf = buf;
s->size = buf_size;
@@ -287,9 +283,9 @@ static int msrle_decode_frame(AVCodecContext *avctx,
return buf_size;
}
static int msrle_decode_end(AVCodecContext *avctx)
static av_cold int msrle_decode_end(AVCodecContext *avctx)
{
MsrleContext *s = (MsrleContext *)avctx->priv_data;
MsrleContext *s = avctx->priv_data;
/* release the last frame */
if (s->frame.data[0])
@@ -308,4 +304,5 @@ AVCodec msrle_decoder = {
msrle_decode_end,
msrle_decode_frame,
CODEC_CAP_DR1,
.long_name= NULL_IF_CONFIG_SMALL("Microsoft RLE"),
};
@@ -2,20 +2,21 @@
* Microsoft Video-1 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
*/
/**
@@ -34,12 +35,9 @@
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "avcodec.h"
#include "dsputil.h"
#define PALETTE_COUNT 256
#define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
#define CHECK_STREAM_PTR(n) \
if ((stream_ptr + n) > s->size ) { \
av_log(s->avctx, AV_LOG_ERROR, " MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \
@@ -50,19 +48,18 @@
typedef struct Msvideo1Context {
AVCodecContext *avctx;
DSPContext dsp;
AVFrame frame;
unsigned char *buf;
const unsigned char *buf;
int size;
int mode_8bit; /* if it's not 8-bit, it's 16-bit */
} Msvideo1Context;
static int msvideo1_decode_init(AVCodecContext *avctx)
static av_cold int msvideo1_decode_init(AVCodecContext *avctx)
{
Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
Msvideo1Context *s = avctx->priv_data;
s->avctx = avctx;
@@ -75,9 +72,6 @@ static int msvideo1_decode_init(AVCodecContext *avctx)
avctx->pix_fmt = PIX_FMT_RGB555;
}
avctx->has_b_frames = 0;
dsputil_init(&s->dsp, avctx);
s->frame.data[0] = NULL;
return 0;
@@ -157,8 +151,8 @@ static void msvideo1_decode_8bit(Msvideo1Context *s)
for (pixel_y = 0; pixel_y < 4; pixel_y++) {
for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
pixels[pixel_ptr++] =
colors[((pixel_y & 0x2) << 1) +
pixels[pixel_ptr++] =
colors[((pixel_y & 0x2) << 1) +
(pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
pixel_ptr -= row_dec;
}
@@ -244,31 +238,31 @@ static void msvideo1_decode_16bit(Msvideo1Context *s)
flags = (byte_b << 8) | byte_a;
CHECK_STREAM_PTR(4);
colors[0] = LE_16(&s->buf[stream_ptr]);
colors[0] = AV_RL16(&s->buf[stream_ptr]);
stream_ptr += 2;
colors[1] = LE_16(&s->buf[stream_ptr]);
colors[1] = AV_RL16(&s->buf[stream_ptr]);
stream_ptr += 2;
if (colors[0] & 0x8000) {
/* 8-color encoding */
CHECK_STREAM_PTR(12);
colors[2] = LE_16(&s->buf[stream_ptr]);
colors[2] = AV_RL16(&s->buf[stream_ptr]);
stream_ptr += 2;
colors[3] = LE_16(&s->buf[stream_ptr]);
colors[3] = AV_RL16(&s->buf[stream_ptr]);
stream_ptr += 2;
colors[4] = LE_16(&s->buf[stream_ptr]);
colors[4] = AV_RL16(&s->buf[stream_ptr]);
stream_ptr += 2;
colors[5] = LE_16(&s->buf[stream_ptr]);
colors[5] = AV_RL16(&s->buf[stream_ptr]);
stream_ptr += 2;
colors[6] = LE_16(&s->buf[stream_ptr]);
colors[6] = AV_RL16(&s->buf[stream_ptr]);
stream_ptr += 2;
colors[7] = LE_16(&s->buf[stream_ptr]);
colors[7] = AV_RL16(&s->buf[stream_ptr]);
stream_ptr += 2;
for (pixel_y = 0; pixel_y < 4; pixel_y++) {
for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
pixels[pixel_ptr++] =
colors[((pixel_y & 0x2) << 1) +
pixels[pixel_ptr++] =
colors[((pixel_y & 0x2) << 1) +
(pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
pixel_ptr -= row_dec;
}
@@ -299,13 +293,9 @@ static void msvideo1_decode_16bit(Msvideo1Context *s)
static int msvideo1_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
const uint8_t *buf, int buf_size)
{
Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
/* no supplementary picture */
if (buf_size == 0)
return 0;
Msvideo1Context *s = avctx->priv_data;
s->buf = buf;
s->size = buf_size;
@@ -329,9 +319,9 @@ static int msvideo1_decode_frame(AVCodecContext *avctx,
return buf_size;
}
static int msvideo1_decode_end(AVCodecContext *avctx)
static av_cold int msvideo1_decode_end(AVCodecContext *avctx)
{
Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
Msvideo1Context *s = avctx->priv_data;
if (s->frame.data[0])
avctx->release_buffer(avctx, &s->frame);
@@ -349,4 +339,5 @@ AVCodec msvideo1_decoder = {
msvideo1_decode_end,
msvideo1_decode_frame,
CODEC_CAP_DR1,
.long_name= NULL_IF_CONFIG_SMALL("Microsoft Video 1"),
};