Update avcodec to 20080825
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27543 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2004 François Revol <[email protected]>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
//#define DEBUG
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
typedef struct ThreadContext{
|
||||
AVCodecContext *avctx;
|
||||
thread_id thread;
|
||||
sem_id work_sem;
|
||||
sem_id done_sem;
|
||||
int (*func)(AVCodecContext *c, void *arg);
|
||||
void *arg;
|
||||
int ret;
|
||||
}ThreadContext;
|
||||
|
||||
// it's odd Be never patented that :D
|
||||
struct benaphore {
|
||||
vint32 atom;
|
||||
sem_id sem;
|
||||
};
|
||||
static inline int lock_ben(struct benaphore *ben)
|
||||
{
|
||||
if (atomic_add(&ben->atom, 1) > 0)
|
||||
return acquire_sem(ben->sem);
|
||||
return B_OK;
|
||||
}
|
||||
static inline int unlock_ben(struct benaphore *ben)
|
||||
{
|
||||
if (atomic_add(&ben->atom, -1) > 1)
|
||||
return release_sem(ben->sem);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
static struct benaphore av_thread_lib_ben;
|
||||
|
||||
static int32 ff_thread_func(void *v){
|
||||
ThreadContext *c= v;
|
||||
|
||||
for(;;){
|
||||
//printf("thread_func %X enter wait\n", (int)v); fflush(stdout);
|
||||
acquire_sem(c->work_sem);
|
||||
//printf("thread_func %X after wait (func=%X)\n", (int)v, (int)c->func); fflush(stdout);
|
||||
if(c->func)
|
||||
c->ret= c->func(c->avctx, c->arg);
|
||||
else
|
||||
return 0;
|
||||
//printf("thread_func %X signal complete\n", (int)v); fflush(stdout);
|
||||
release_sem(c->done_sem);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free what has been allocated by avcodec_thread_init().
|
||||
* Must be called after decoding has finished, especially do not call while avcodec_thread_execute() is running.
|
||||
*/
|
||||
void avcodec_thread_free(AVCodecContext *s){
|
||||
ThreadContext *c= s->thread_opaque;
|
||||
int i;
|
||||
int32 ret;
|
||||
|
||||
for(i=0; i<s->thread_count; i++){
|
||||
|
||||
c[i].func= NULL;
|
||||
release_sem(c[i].work_sem);
|
||||
wait_for_thread(c[i].thread, &ret);
|
||||
if(c[i].work_sem > B_OK) delete_sem(c[i].work_sem);
|
||||
if(c[i].done_sem > B_OK) delete_sem(c[i].done_sem);
|
||||
}
|
||||
|
||||
av_freep(&s->thread_opaque);
|
||||
}
|
||||
|
||||
int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count){
|
||||
ThreadContext *c= s->thread_opaque;
|
||||
int i;
|
||||
|
||||
assert(s == c->avctx);
|
||||
assert(count <= s->thread_count);
|
||||
|
||||
/* note, we can be certain that this is not called with the same AVCodecContext by different threads at the same time */
|
||||
|
||||
for(i=0; i<count; i++){
|
||||
c[i].arg= arg[i];
|
||||
c[i].func= func;
|
||||
c[i].ret= 12345;
|
||||
|
||||
release_sem(c[i].work_sem);
|
||||
}
|
||||
for(i=0; i<count; i++){
|
||||
acquire_sem(c[i].done_sem);
|
||||
|
||||
c[i].func= NULL;
|
||||
if(ret) ret[i]= c[i].ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avcodec_thread_init(AVCodecContext *s, int thread_count){
|
||||
int i;
|
||||
ThreadContext *c;
|
||||
|
||||
s->thread_count= thread_count;
|
||||
|
||||
assert(!s->thread_opaque);
|
||||
c= av_mallocz(sizeof(ThreadContext)*thread_count);
|
||||
s->thread_opaque= c;
|
||||
|
||||
for(i=0; i<thread_count; i++){
|
||||
//printf("init semaphors %d\n", i); fflush(stdout);
|
||||
c[i].avctx= s;
|
||||
|
||||
if((c[i].work_sem = create_sem(0, "ff work sem")) < B_OK)
|
||||
goto fail;
|
||||
if((c[i].done_sem = create_sem(0, "ff done sem")) < B_OK)
|
||||
goto fail;
|
||||
|
||||
//printf("create thread %d\n", i); fflush(stdout);
|
||||
c[i].thread = spawn_thread(ff_thread_func, "libavcodec thread", B_LOW_PRIORITY, &c[i] );
|
||||
if( c[i].thread < B_OK ) goto fail;
|
||||
resume_thread(c[i].thread );
|
||||
}
|
||||
//printf("init done\n"); fflush(stdout);
|
||||
|
||||
s->execute= avcodec_thread_execute;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
avcodec_thread_free(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* provide a mean to serialize calls to avcodec_*() for thread safety. */
|
||||
|
||||
int avcodec_thread_lock_lib(void)
|
||||
{
|
||||
return lock_ben(&av_thread_lib_ben);
|
||||
}
|
||||
|
||||
int avcodec_thread_unlock_lib(void)
|
||||
{
|
||||
return unlock_ben(&av_thread_lib_ben);
|
||||
}
|
||||
|
||||
/* our versions of _init and _fini (which are called by those actually from crt.o) */
|
||||
|
||||
void initialize_after(void)
|
||||
{
|
||||
av_thread_lib_ben.atom = 0;
|
||||
av_thread_lib_ben.sem = create_sem(0, "libavcodec benaphore");
|
||||
}
|
||||
|
||||
void uninitialize_before(void)
|
||||
{
|
||||
delete_sem(av_thread_lib_ben.sem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Bethesda VID video decoder
|
||||
* Copyright (C) 2007 Nicholas Tung
|
||||
*
|
||||
* 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 bethsoftvideo.c
|
||||
* @brief Bethesda Softworks VID Video Decoder
|
||||
* @author Nicholas Tung [ntung (at. ntung com] (2007-03)
|
||||
* @sa http://wiki.multimedia.cx/index.php?title=Bethsoft_VID
|
||||
* @sa http://www.svatopluk.com/andux/docs/dfvid.html
|
||||
*/
|
||||
|
||||
#include "libavutil/common.h"
|
||||
#include "dsputil.h"
|
||||
#include "bethsoftvideo.h"
|
||||
#include "bytestream.h"
|
||||
|
||||
typedef struct BethsoftvidContext {
|
||||
AVFrame frame;
|
||||
} BethsoftvidContext;
|
||||
|
||||
static av_cold int bethsoftvid_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
BethsoftvidContext *vid = avctx->priv_data;
|
||||
vid->frame.reference = 1;
|
||||
vid->frame.buffer_hints = FF_BUFFER_HINTS_VALID |
|
||||
FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
|
||||
avctx->pix_fmt = PIX_FMT_PAL8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_palette(AVFrame * frame, const uint8_t * palette_buffer)
|
||||
{
|
||||
uint32_t * palette = (uint32_t *)frame->data[1];
|
||||
int a;
|
||||
for(a = 0; a < 256; a++){
|
||||
palette[a] = AV_RB24(&palette_buffer[a * 3]) * 4;
|
||||
}
|
||||
frame->palette_has_changed = 1;
|
||||
}
|
||||
|
||||
static int bethsoftvid_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
BethsoftvidContext * vid = avctx->priv_data;
|
||||
char block_type;
|
||||
uint8_t * dst;
|
||||
uint8_t * frame_end;
|
||||
int remaining = avctx->width; // number of bytes remaining on a line
|
||||
const int wrap_to_next_line = vid->frame.linesize[0] - avctx->width;
|
||||
int code;
|
||||
int yoffset;
|
||||
|
||||
if (avctx->reget_buffer(avctx, &vid->frame)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
dst = vid->frame.data[0];
|
||||
frame_end = vid->frame.data[0] + vid->frame.linesize[0] * avctx->height;
|
||||
|
||||
switch(block_type = *buf++){
|
||||
case PALETTE_BLOCK:
|
||||
set_palette(&vid->frame, buf);
|
||||
return 0;
|
||||
case VIDEO_YOFF_P_FRAME:
|
||||
yoffset = bytestream_get_le16(&buf);
|
||||
if(yoffset >= avctx->height)
|
||||
return -1;
|
||||
dst += vid->frame.linesize[0] * yoffset;
|
||||
}
|
||||
|
||||
// main code
|
||||
while((code = *buf++)){
|
||||
int length = code & 0x7f;
|
||||
|
||||
// copy any bytes starting at the current position, and ending at the frame width
|
||||
while(length > remaining){
|
||||
if(code < 0x80)
|
||||
bytestream_get_buffer(&buf, dst, remaining);
|
||||
else if(block_type == VIDEO_I_FRAME)
|
||||
memset(dst, buf[0], remaining);
|
||||
length -= remaining; // decrement the number of bytes to be copied
|
||||
dst += remaining + wrap_to_next_line; // skip over extra bytes at end of frame
|
||||
remaining = avctx->width;
|
||||
if(dst == frame_end)
|
||||
goto end;
|
||||
}
|
||||
|
||||
// copy any remaining bytes after / if line overflows
|
||||
if(code < 0x80)
|
||||
bytestream_get_buffer(&buf, dst, length);
|
||||
else if(block_type == VIDEO_I_FRAME)
|
||||
memset(dst, *buf++, length);
|
||||
remaining -= length;
|
||||
dst += length;
|
||||
}
|
||||
end:
|
||||
|
||||
*data_size = sizeof(AVFrame);
|
||||
*(AVFrame*)data = vid->frame;
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static av_cold int bethsoftvid_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
BethsoftvidContext * vid = avctx->priv_data;
|
||||
if(vid->frame.data[0])
|
||||
avctx->release_buffer(avctx, &vid->frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVCodec bethsoftvid_decoder = {
|
||||
.name = "bethsoftvid",
|
||||
.type = CODEC_TYPE_VIDEO,
|
||||
.id = CODEC_ID_BETHSOFTVID,
|
||||
.priv_data_size = sizeof(BethsoftvidContext),
|
||||
.init = bethsoftvid_decode_init,
|
||||
.close = bethsoftvid_decode_end,
|
||||
.decode = bethsoftvid_decode_frame,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Bethesda VID video"),
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Bethesda VID video decoder
|
||||
* Copyright (C) 2007 Nicholas Tung
|
||||
*
|
||||
* 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_BETHSOFTVIDEO_H
|
||||
#define FFMPEG_BETHSOFTVIDEO_H
|
||||
|
||||
enum BethsoftVidBlockType
|
||||
{
|
||||
PALETTE_BLOCK = 0x02,
|
||||
FIRST_AUDIO_BLOCK = 0x7c,
|
||||
AUDIO_BLOCK = 0x7d,
|
||||
VIDEO_I_FRAME = 0x03,
|
||||
VIDEO_P_FRAME = 0x01,
|
||||
VIDEO_YOFF_P_FRAME = 0x04,
|
||||
EOF_BLOCK = 0x14,
|
||||
};
|
||||
|
||||
#endif /* FFMPEG_BETHSOFTVIDEO_H */
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Brute Force & Ignorance (BFI) video decoder
|
||||
* Copyright (c) 2008 Sisir Koppaka
|
||||
*
|
||||
* 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 bfi.c
|
||||
* @brief Brute Force & Ignorance (.bfi) video decoder
|
||||
* @author Sisir Koppaka ( sisir.koppaka at gmail dot com )
|
||||
* @sa http://wiki.multimedia.cx/index.php?title=BFI
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
|
||||
typedef struct BFIContext {
|
||||
AVCodecContext *avctx;
|
||||
AVFrame frame;
|
||||
uint8_t *dst;
|
||||
} BFIContext;
|
||||
|
||||
static int bfi_decode_init(AVCodecContext * avctx)
|
||||
{
|
||||
BFIContext *bfi = avctx->priv_data;
|
||||
avctx->pix_fmt = PIX_FMT_PAL8;
|
||||
bfi->dst = av_mallocz(avctx->width * avctx->height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfi_decode_frame(AVCodecContext * avctx, void *data,
|
||||
int *data_size, const uint8_t * buf,
|
||||
int buf_size)
|
||||
{
|
||||
BFIContext *bfi = avctx->priv_data;
|
||||
uint8_t *dst = bfi->dst;
|
||||
uint8_t *src, *dst_offset, colour1, colour2;
|
||||
uint8_t *frame_end = bfi->dst + avctx->width * avctx->height;
|
||||
uint32_t *pal;
|
||||
int i, j, height = avctx->height;
|
||||
|
||||
if (bfi->frame.data[0])
|
||||
avctx->release_buffer(avctx, &bfi->frame);
|
||||
|
||||
bfi->frame.reference = 1;
|
||||
|
||||
if (avctx->get_buffer(avctx, &bfi->frame) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set frame parameters and palette, if necessary */
|
||||
if (!avctx->frame_number) {
|
||||
bfi->frame.pict_type = FF_I_TYPE;
|
||||
bfi->frame.key_frame = 1;
|
||||
/* Setting the palette */
|
||||
if(avctx->extradata_size>768) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Palette is too large.\n");
|
||||
return -1;
|
||||
}
|
||||
pal = (uint32_t *) bfi->frame.data[1];
|
||||
for (i = 0; i < avctx->extradata_size / 3; i++) {
|
||||
int shift = 16;
|
||||
*pal = 0;
|
||||
for (j = 0; j < 3; j++, shift -= 8)
|
||||
*pal +=
|
||||
((avctx->extradata[i * 3 + j] << 2) |
|
||||
(avctx->extradata[i * 3 + j] >> 4)) << shift;
|
||||
pal++;
|
||||
}
|
||||
bfi->frame.palette_has_changed = 1;
|
||||
} else {
|
||||
bfi->frame.pict_type = FF_P_TYPE;
|
||||
bfi->frame.key_frame = 0;
|
||||
}
|
||||
|
||||
buf += 4; //Unpacked size, not required.
|
||||
|
||||
while (dst != frame_end) {
|
||||
static const uint8_t lentab[4]={0,2,0,1};
|
||||
unsigned int byte = *buf++, offset;
|
||||
unsigned int code = byte >> 6;
|
||||
unsigned int length = byte & ~0xC0;
|
||||
|
||||
/* Get length and offset(if required) */
|
||||
if (length == 0) {
|
||||
if (code == 1) {
|
||||
length = bytestream_get_byte(&buf);
|
||||
offset = bytestream_get_le16(&buf);
|
||||
} else {
|
||||
length = bytestream_get_le16(&buf);
|
||||
if (code == 2 && length == 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (code == 1)
|
||||
offset = bytestream_get_byte(&buf);
|
||||
}
|
||||
|
||||
/* Do boundary check */
|
||||
if (dst + (length<<lentab[code]) > frame_end)
|
||||
break;
|
||||
|
||||
switch (code) {
|
||||
|
||||
case 0: //Normal Chain
|
||||
bytestream_get_buffer(&buf, dst, length);
|
||||
dst += length;
|
||||
break;
|
||||
|
||||
case 1: //Back Chain
|
||||
dst_offset = dst - offset;
|
||||
length *= 4; //Convert dwords to bytes.
|
||||
if (dst_offset < bfi->dst)
|
||||
break;
|
||||
while (length--)
|
||||
*dst++ = *dst_offset++;
|
||||
break;
|
||||
|
||||
case 2: //Skip Chain
|
||||
dst += length;
|
||||
break;
|
||||
|
||||
case 3: //Fill Chain
|
||||
colour1 = bytestream_get_byte(&buf);
|
||||
colour2 = bytestream_get_byte(&buf);
|
||||
while (length--) {
|
||||
*dst++ = colour1;
|
||||
*dst++ = colour2;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
src = bfi->dst;
|
||||
dst = bfi->frame.data[0];
|
||||
while (height--) {
|
||||
memcpy(dst, src, avctx->width);
|
||||
src += avctx->width;
|
||||
dst += bfi->frame.linesize[0];
|
||||
}
|
||||
*data_size = sizeof(AVFrame);
|
||||
*(AVFrame *) data = bfi->frame;
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static int bfi_decode_close(AVCodecContext * avctx)
|
||||
{
|
||||
BFIContext *bfi = avctx->priv_data;
|
||||
if (bfi->frame.data[0])
|
||||
avctx->release_buffer(avctx, &bfi->frame);
|
||||
av_free(bfi->dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVCodec bfi_decoder = {
|
||||
.name = "bfi",
|
||||
.type = CODEC_TYPE_VIDEO,
|
||||
.id = CODEC_ID_BFI,
|
||||
.priv_data_size = sizeof(BFIContext),
|
||||
.init = bfi_decode_init,
|
||||
.close = bfi_decode_close,
|
||||
.decode = bfi_decode_frame,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"),
|
||||
};
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Common bit i/o utils
|
||||
* Copyright (c) 2000, 2001 Fabrice Bellard.
|
||||
* Copyright (c) 2002-2004 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* alternative bitstream reader & writer by Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* 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 bitstream.c
|
||||
* bitstream api.
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bitstream.h"
|
||||
|
||||
const uint8_t ff_log2_run[32]={
|
||||
0, 0, 0, 0, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 3, 3, 3, 3,
|
||||
4, 4, 5, 5, 6, 6, 7, 7,
|
||||
8, 9,10,11,12,13,14,15
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as av_mallocz_static(), but does a realloc.
|
||||
*
|
||||
* @param[in] ptr The block of memory to reallocate.
|
||||
* @param[in] size The requested size.
|
||||
* @return Block of memory of requested size.
|
||||
* @deprecated. Code which uses ff_realloc_static is broken/misdesigned
|
||||
* and should correctly use static arrays
|
||||
*/
|
||||
attribute_deprecated av_alloc_size(2)
|
||||
static void *ff_realloc_static(void *ptr, unsigned int size);
|
||||
|
||||
static void *ff_realloc_static(void *ptr, unsigned int size)
|
||||
{
|
||||
return av_realloc(ptr, size);
|
||||
}
|
||||
|
||||
void align_put_bits(PutBitContext *s)
|
||||
{
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
put_bits(s,( - s->index) & 7,0);
|
||||
#else
|
||||
put_bits(s,s->bit_left & 7,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ff_put_string(PutBitContext * pbc, const char *s, int put_zero)
|
||||
{
|
||||
while(*s){
|
||||
put_bits(pbc, 8, *s);
|
||||
s++;
|
||||
}
|
||||
if(put_zero)
|
||||
put_bits(pbc, 8, 0);
|
||||
}
|
||||
|
||||
void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length)
|
||||
{
|
||||
const uint16_t *srcw= (const uint16_t*)src;
|
||||
int words= length>>4;
|
||||
int bits= length&15;
|
||||
int i;
|
||||
|
||||
if(length==0) return;
|
||||
|
||||
if(ENABLE_SMALL || words < 16 || put_bits_count(pb)&7){
|
||||
for(i=0; i<words; i++) put_bits(pb, 16, be2me_16(srcw[i]));
|
||||
}else{
|
||||
for(i=0; put_bits_count(pb)&31; i++)
|
||||
put_bits(pb, 8, src[i]);
|
||||
flush_put_bits(pb);
|
||||
memcpy(pbBufPtr(pb), src+i, 2*words-i);
|
||||
skip_put_bytes(pb, 2*words-i);
|
||||
}
|
||||
|
||||
put_bits(pb, bits, be2me_16(srcw[words])>>(16-bits));
|
||||
}
|
||||
|
||||
/* VLC decoding */
|
||||
|
||||
//#define DEBUG_VLC
|
||||
|
||||
#define GET_DATA(v, table, i, wrap, size) \
|
||||
{\
|
||||
const uint8_t *ptr = (const uint8_t *)table + i * wrap;\
|
||||
switch(size) {\
|
||||
case 1:\
|
||||
v = *(const uint8_t *)ptr;\
|
||||
break;\
|
||||
case 2:\
|
||||
v = *(const uint16_t *)ptr;\
|
||||
break;\
|
||||
default:\
|
||||
v = *(const uint32_t *)ptr;\
|
||||
break;\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
static int alloc_table(VLC *vlc, int size, int use_static)
|
||||
{
|
||||
int index;
|
||||
index = vlc->table_size;
|
||||
vlc->table_size += size;
|
||||
if (vlc->table_size > vlc->table_allocated) {
|
||||
if(use_static>1)
|
||||
abort(); //cant do anything, init_vlc() is used with too little memory
|
||||
vlc->table_allocated += (1 << vlc->bits);
|
||||
if(use_static)
|
||||
vlc->table = ff_realloc_static(vlc->table,
|
||||
sizeof(VLC_TYPE) * 2 * vlc->table_allocated);
|
||||
else
|
||||
vlc->table = av_realloc(vlc->table,
|
||||
sizeof(VLC_TYPE) * 2 * vlc->table_allocated);
|
||||
if (!vlc->table)
|
||||
return -1;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static int build_table(VLC *vlc, int table_nb_bits,
|
||||
int nb_codes,
|
||||
const void *bits, int bits_wrap, int bits_size,
|
||||
const void *codes, int codes_wrap, int codes_size,
|
||||
const void *symbols, int symbols_wrap, int symbols_size,
|
||||
uint32_t code_prefix, int n_prefix, int flags)
|
||||
{
|
||||
int i, j, k, n, table_size, table_index, nb, n1, index, code_prefix2, symbol;
|
||||
uint32_t code;
|
||||
VLC_TYPE (*table)[2];
|
||||
|
||||
table_size = 1 << table_nb_bits;
|
||||
table_index = alloc_table(vlc, table_size, flags & (INIT_VLC_USE_STATIC|INIT_VLC_USE_NEW_STATIC));
|
||||
#ifdef DEBUG_VLC
|
||||
av_log(NULL,AV_LOG_DEBUG,"new table index=%d size=%d code_prefix=%x n=%d\n",
|
||||
table_index, table_size, code_prefix, n_prefix);
|
||||
#endif
|
||||
if (table_index < 0)
|
||||
return -1;
|
||||
table = &vlc->table[table_index];
|
||||
|
||||
for(i=0;i<table_size;i++) {
|
||||
table[i][1] = 0; //bits
|
||||
table[i][0] = -1; //codes
|
||||
}
|
||||
|
||||
/* first pass: map codes and compute auxillary table sizes */
|
||||
for(i=0;i<nb_codes;i++) {
|
||||
GET_DATA(n, bits, i, bits_wrap, bits_size);
|
||||
GET_DATA(code, codes, i, codes_wrap, codes_size);
|
||||
/* we accept tables with holes */
|
||||
if (n <= 0)
|
||||
continue;
|
||||
if (!symbols)
|
||||
symbol = i;
|
||||
else
|
||||
GET_DATA(symbol, symbols, i, symbols_wrap, symbols_size);
|
||||
#if defined(DEBUG_VLC) && 0
|
||||
av_log(NULL,AV_LOG_DEBUG,"i=%d n=%d code=0x%x\n", i, n, code);
|
||||
#endif
|
||||
/* if code matches the prefix, it is in the table */
|
||||
n -= n_prefix;
|
||||
if(flags & INIT_VLC_LE)
|
||||
code_prefix2= code & (n_prefix>=32 ? 0xffffffff : (1 << n_prefix)-1);
|
||||
else
|
||||
code_prefix2= code >> n;
|
||||
if (n > 0 && code_prefix2 == code_prefix) {
|
||||
if (n <= table_nb_bits) {
|
||||
/* no need to add another table */
|
||||
j = (code << (table_nb_bits - n)) & (table_size - 1);
|
||||
nb = 1 << (table_nb_bits - n);
|
||||
for(k=0;k<nb;k++) {
|
||||
if(flags & INIT_VLC_LE)
|
||||
j = (code >> n_prefix) + (k<<n);
|
||||
#ifdef DEBUG_VLC
|
||||
av_log(NULL, AV_LOG_DEBUG, "%4x: code=%d n=%d\n",
|
||||
j, i, n);
|
||||
#endif
|
||||
if (table[j][1] /*bits*/ != 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "incorrect codes\n");
|
||||
return -1;
|
||||
}
|
||||
table[j][1] = n; //bits
|
||||
table[j][0] = symbol;
|
||||
j++;
|
||||
}
|
||||
} else {
|
||||
n -= table_nb_bits;
|
||||
j = (code >> ((flags & INIT_VLC_LE) ? n_prefix : n)) & ((1 << table_nb_bits) - 1);
|
||||
#ifdef DEBUG_VLC
|
||||
av_log(NULL,AV_LOG_DEBUG,"%4x: n=%d (subtable)\n",
|
||||
j, n);
|
||||
#endif
|
||||
/* compute table size */
|
||||
n1 = -table[j][1]; //bits
|
||||
if (n > n1)
|
||||
n1 = n;
|
||||
table[j][1] = -n1; //bits
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* second pass : fill auxillary tables recursively */
|
||||
for(i=0;i<table_size;i++) {
|
||||
n = table[i][1]; //bits
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
if (n > table_nb_bits) {
|
||||
n = table_nb_bits;
|
||||
table[i][1] = -n; //bits
|
||||
}
|
||||
index = build_table(vlc, n, nb_codes,
|
||||
bits, bits_wrap, bits_size,
|
||||
codes, codes_wrap, codes_size,
|
||||
symbols, symbols_wrap, symbols_size,
|
||||
(flags & INIT_VLC_LE) ? (code_prefix | (i << n_prefix)) : ((code_prefix << table_nb_bits) | i),
|
||||
n_prefix + table_nb_bits, flags);
|
||||
if (index < 0)
|
||||
return -1;
|
||||
/* note: realloc has been done, so reload tables */
|
||||
table = &vlc->table[table_index];
|
||||
table[i][0] = index; //code
|
||||
}
|
||||
}
|
||||
return table_index;
|
||||
}
|
||||
|
||||
|
||||
/* Build VLC decoding tables suitable for use with get_vlc().
|
||||
|
||||
'nb_bits' set thee decoding table size (2^nb_bits) entries. The
|
||||
bigger it is, the faster is the decoding. But it should not be too
|
||||
big to save memory and L1 cache. '9' is a good compromise.
|
||||
|
||||
'nb_codes' : number of vlcs codes
|
||||
|
||||
'bits' : table which gives the size (in bits) of each vlc code.
|
||||
|
||||
'codes' : table which gives the bit pattern of of each vlc code.
|
||||
|
||||
'symbols' : table which gives the values to be returned from get_vlc().
|
||||
|
||||
'xxx_wrap' : give the number of bytes between each entry of the
|
||||
'bits' or 'codes' tables.
|
||||
|
||||
'xxx_size' : gives the number of bytes of each entry of the 'bits'
|
||||
or 'codes' tables.
|
||||
|
||||
'wrap' and 'size' allows to use any memory configuration and types
|
||||
(byte/word/long) to store the 'bits', 'codes', and 'symbols' tables.
|
||||
|
||||
'use_static' should be set to 1 for tables, which should be freed
|
||||
with av_free_static(), 0 if free_vlc() will be used.
|
||||
*/
|
||||
int init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
|
||||
const void *bits, int bits_wrap, int bits_size,
|
||||
const void *codes, int codes_wrap, int codes_size,
|
||||
const void *symbols, int symbols_wrap, int symbols_size,
|
||||
int flags)
|
||||
{
|
||||
vlc->bits = nb_bits;
|
||||
if(flags & INIT_VLC_USE_NEW_STATIC){
|
||||
if(vlc->table_size && vlc->table_size == vlc->table_allocated){
|
||||
return 0;
|
||||
}else if(vlc->table_size){
|
||||
abort(); // fatal error, we are called on a partially initialized table
|
||||
}
|
||||
}else if(!(flags & INIT_VLC_USE_STATIC)) {
|
||||
vlc->table = NULL;
|
||||
vlc->table_allocated = 0;
|
||||
vlc->table_size = 0;
|
||||
} else {
|
||||
/* Static tables are initially always NULL, return
|
||||
if vlc->table != NULL to avoid double allocation */
|
||||
if(vlc->table)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VLC
|
||||
av_log(NULL,AV_LOG_DEBUG,"build table nb_codes=%d\n", nb_codes);
|
||||
#endif
|
||||
|
||||
if (build_table(vlc, nb_bits, nb_codes,
|
||||
bits, bits_wrap, bits_size,
|
||||
codes, codes_wrap, codes_size,
|
||||
symbols, symbols_wrap, symbols_size,
|
||||
0, 0, flags) < 0) {
|
||||
av_freep(&vlc->table);
|
||||
return -1;
|
||||
}
|
||||
if((flags & INIT_VLC_USE_NEW_STATIC) && vlc->table_size != vlc->table_allocated)
|
||||
av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void free_vlc(VLC *vlc)
|
||||
{
|
||||
av_freep(&vlc->table);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,931 @@
|
||||
/*
|
||||
* copyright (c) 2004 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* 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 bitstream.h
|
||||
* bitstream api header.
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_BITSTREAM_H
|
||||
#define FFMPEG_BITSTREAM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "bswap.h"
|
||||
#include "common.h"
|
||||
#include "intreadwrite.h"
|
||||
#include "log.h"
|
||||
|
||||
#if defined(ALT_BITSTREAM_READER_LE) && !defined(ALT_BITSTREAM_READER)
|
||||
# define ALT_BITSTREAM_READER
|
||||
#endif
|
||||
|
||||
//#define ALT_BITSTREAM_WRITER
|
||||
//#define ALIGNED_BITSTREAM_WRITER
|
||||
#if !defined(LIBMPEG2_BITSTREAM_READER) && !defined(A32_BITSTREAM_READER) && !defined(ALT_BITSTREAM_READER)
|
||||
# ifdef ARCH_ARMV4L
|
||||
# define A32_BITSTREAM_READER
|
||||
# else
|
||||
# define ALT_BITSTREAM_READER
|
||||
//#define LIBMPEG2_BITSTREAM_READER
|
||||
//#define A32_BITSTREAM_READER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern const uint8_t ff_reverse[256];
|
||||
|
||||
#if defined(ARCH_X86)
|
||||
// avoid +32 for shift optimization (gcc should do that ...)
|
||||
static inline int32_t NEG_SSR32( int32_t a, int8_t s){
|
||||
asm ("sarl %1, %0\n\t"
|
||||
: "+r" (a)
|
||||
: "ic" ((uint8_t)(-s))
|
||||
);
|
||||
return a;
|
||||
}
|
||||
static inline uint32_t NEG_USR32(uint32_t a, int8_t s){
|
||||
asm ("shrl %1, %0\n\t"
|
||||
: "+r" (a)
|
||||
: "ic" ((uint8_t)(-s))
|
||||
);
|
||||
return a;
|
||||
}
|
||||
#else
|
||||
# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s)))
|
||||
# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s)))
|
||||
#endif
|
||||
|
||||
/* bit output */
|
||||
|
||||
/* buf and buf_end must be present and used by every alternative writer. */
|
||||
typedef struct PutBitContext {
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
uint8_t *buf, *buf_end;
|
||||
int index;
|
||||
#else
|
||||
uint32_t bit_buf;
|
||||
int bit_left;
|
||||
uint8_t *buf, *buf_ptr, *buf_end;
|
||||
#endif
|
||||
} PutBitContext;
|
||||
|
||||
static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
|
||||
{
|
||||
if(buffer_size < 0) {
|
||||
buffer_size = 0;
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
s->buf = buffer;
|
||||
s->buf_end = s->buf + buffer_size;
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
s->index=0;
|
||||
((uint32_t*)(s->buf))[0]=0;
|
||||
// memset(buffer, 0, buffer_size);
|
||||
#else
|
||||
s->buf_ptr = s->buf;
|
||||
s->bit_left=32;
|
||||
s->bit_buf=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* return the number of bits output */
|
||||
static inline int put_bits_count(PutBitContext *s)
|
||||
{
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
return s->index;
|
||||
#else
|
||||
return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* pad the end of the output stream with zeros */
|
||||
static inline void flush_put_bits(PutBitContext *s)
|
||||
{
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
align_put_bits(s);
|
||||
#else
|
||||
s->bit_buf<<= s->bit_left;
|
||||
while (s->bit_left < 32) {
|
||||
/* XXX: should test end of buffer */
|
||||
*s->buf_ptr++=s->bit_buf >> 24;
|
||||
s->bit_buf<<=8;
|
||||
s->bit_left+=8;
|
||||
}
|
||||
s->bit_left=32;
|
||||
s->bit_buf=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void align_put_bits(PutBitContext *s);
|
||||
void ff_put_string(PutBitContext * pbc, const char *s, int put_zero);
|
||||
void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length);
|
||||
|
||||
/* bit input */
|
||||
/* buffer, buffer_end and size_in_bits must be present and used by every reader */
|
||||
typedef struct GetBitContext {
|
||||
const uint8_t *buffer, *buffer_end;
|
||||
#ifdef ALT_BITSTREAM_READER
|
||||
int index;
|
||||
#elif defined LIBMPEG2_BITSTREAM_READER
|
||||
uint8_t *buffer_ptr;
|
||||
uint32_t cache;
|
||||
int bit_count;
|
||||
#elif defined A32_BITSTREAM_READER
|
||||
uint32_t *buffer_ptr;
|
||||
uint32_t cache0;
|
||||
uint32_t cache1;
|
||||
int bit_count;
|
||||
#endif
|
||||
int size_in_bits;
|
||||
} GetBitContext;
|
||||
|
||||
#define VLC_TYPE int16_t
|
||||
|
||||
typedef struct VLC {
|
||||
int bits;
|
||||
VLC_TYPE (*table)[2]; ///< code, bits
|
||||
int table_size, table_allocated;
|
||||
} VLC;
|
||||
|
||||
typedef struct RL_VLC_ELEM {
|
||||
int16_t level;
|
||||
int8_t len;
|
||||
uint8_t run;
|
||||
} RL_VLC_ELEM;
|
||||
|
||||
#if defined(ARCH_SPARC) || defined(ARCH_ARMV4L) || defined(ARCH_MIPS) || defined(ARCH_BFIN)
|
||||
#define UNALIGNED_STORES_ARE_BAD
|
||||
#endif
|
||||
|
||||
#ifndef ALT_BITSTREAM_WRITER
|
||||
static inline void put_bits(PutBitContext *s, int n, unsigned int value)
|
||||
{
|
||||
unsigned int bit_buf;
|
||||
int bit_left;
|
||||
|
||||
// printf("put_bits=%d %x\n", n, value);
|
||||
assert(n == 32 || value < (1U << n));
|
||||
|
||||
bit_buf = s->bit_buf;
|
||||
bit_left = s->bit_left;
|
||||
|
||||
// printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
|
||||
/* XXX: optimize */
|
||||
if (n < bit_left) {
|
||||
bit_buf = (bit_buf<<n) | value;
|
||||
bit_left-=n;
|
||||
} else {
|
||||
bit_buf<<=bit_left;
|
||||
bit_buf |= value >> (n - bit_left);
|
||||
#ifdef UNALIGNED_STORES_ARE_BAD
|
||||
if (3 & (intptr_t) s->buf_ptr) {
|
||||
s->buf_ptr[0] = bit_buf >> 24;
|
||||
s->buf_ptr[1] = bit_buf >> 16;
|
||||
s->buf_ptr[2] = bit_buf >> 8;
|
||||
s->buf_ptr[3] = bit_buf ;
|
||||
} else
|
||||
#endif
|
||||
*(uint32_t *)s->buf_ptr = be2me_32(bit_buf);
|
||||
//printf("bitbuf = %08x\n", bit_buf);
|
||||
s->buf_ptr+=4;
|
||||
bit_left+=32 - n;
|
||||
bit_buf = value;
|
||||
}
|
||||
|
||||
s->bit_buf = bit_buf;
|
||||
s->bit_left = bit_left;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
static inline void put_bits(PutBitContext *s, int n, unsigned int value)
|
||||
{
|
||||
# ifdef ALIGNED_BITSTREAM_WRITER
|
||||
# if defined(ARCH_X86)
|
||||
asm volatile(
|
||||
"movl %0, %%ecx \n\t"
|
||||
"xorl %%eax, %%eax \n\t"
|
||||
"shrdl %%cl, %1, %%eax \n\t"
|
||||
"shrl %%cl, %1 \n\t"
|
||||
"movl %0, %%ecx \n\t"
|
||||
"shrl $3, %%ecx \n\t"
|
||||
"andl $0xFFFFFFFC, %%ecx \n\t"
|
||||
"bswapl %1 \n\t"
|
||||
"orl %1, (%2, %%ecx) \n\t"
|
||||
"bswapl %%eax \n\t"
|
||||
"addl %3, %0 \n\t"
|
||||
"movl %%eax, 4(%2, %%ecx) \n\t"
|
||||
: "=&r" (s->index), "=&r" (value)
|
||||
: "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n))
|
||||
: "%eax", "%ecx"
|
||||
);
|
||||
# else
|
||||
int index= s->index;
|
||||
uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5);
|
||||
|
||||
value<<= 32-n;
|
||||
|
||||
ptr[0] |= be2me_32(value>>(index&31));
|
||||
ptr[1] = be2me_32(value<<(32-(index&31)));
|
||||
//if(n>24) printf("%d %d\n", n, value);
|
||||
index+= n;
|
||||
s->index= index;
|
||||
# endif
|
||||
# else //ALIGNED_BITSTREAM_WRITER
|
||||
# if defined(ARCH_X86)
|
||||
asm volatile(
|
||||
"movl $7, %%ecx \n\t"
|
||||
"andl %0, %%ecx \n\t"
|
||||
"addl %3, %%ecx \n\t"
|
||||
"negl %%ecx \n\t"
|
||||
"shll %%cl, %1 \n\t"
|
||||
"bswapl %1 \n\t"
|
||||
"movl %0, %%ecx \n\t"
|
||||
"shrl $3, %%ecx \n\t"
|
||||
"orl %1, (%%ecx, %2) \n\t"
|
||||
"addl %3, %0 \n\t"
|
||||
"movl $0, 4(%%ecx, %2) \n\t"
|
||||
: "=&r" (s->index), "=&r" (value)
|
||||
: "r" (s->buf), "r" (n), "0" (s->index), "1" (value)
|
||||
: "%ecx"
|
||||
);
|
||||
# else
|
||||
int index= s->index;
|
||||
uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3));
|
||||
|
||||
ptr[0] |= be2me_32(value<<(32-n-(index&7) ));
|
||||
ptr[1] = 0;
|
||||
//if(n>24) printf("%d %d\n", n, value);
|
||||
index+= n;
|
||||
s->index= index;
|
||||
# endif
|
||||
# endif //!ALIGNED_BITSTREAM_WRITER
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void put_sbits(PutBitContext *pb, int bits, int32_t val)
|
||||
{
|
||||
assert(bits >= 0 && bits <= 31);
|
||||
|
||||
put_bits(pb, bits, val & ((1<<bits)-1));
|
||||
}
|
||||
|
||||
|
||||
static inline uint8_t* pbBufPtr(PutBitContext *s)
|
||||
{
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
return s->buf + (s->index>>3);
|
||||
#else
|
||||
return s->buf_ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* PutBitContext must be flushed & aligned to a byte boundary before calling this.
|
||||
*/
|
||||
static inline void skip_put_bytes(PutBitContext *s, int n){
|
||||
assert((put_bits_count(s)&7)==0);
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
FIXME may need some cleaning of the buffer
|
||||
s->index += n<<3;
|
||||
#else
|
||||
assert(s->bit_left==32);
|
||||
s->buf_ptr += n;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips the given number of bits.
|
||||
* Must only be used if the actual values in the bitstream do not matter.
|
||||
*/
|
||||
static inline void skip_put_bits(PutBitContext *s, int n){
|
||||
#ifdef ALT_BITSTREAM_WRITER
|
||||
s->index += n;
|
||||
#else
|
||||
s->bit_left -= n;
|
||||
s->buf_ptr-= s->bit_left>>5;
|
||||
s->bit_left &= 31;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the end of the buffer.
|
||||
*/
|
||||
static inline void set_put_bits_buffer_size(PutBitContext *s, int size){
|
||||
s->buf_end= s->buf + size;
|
||||
}
|
||||
|
||||
/* Bitstream reader API docs:
|
||||
name
|
||||
abritary name which is used as prefix for the internal variables
|
||||
|
||||
gb
|
||||
getbitcontext
|
||||
|
||||
OPEN_READER(name, gb)
|
||||
loads gb into local variables
|
||||
|
||||
CLOSE_READER(name, gb)
|
||||
stores local vars in gb
|
||||
|
||||
UPDATE_CACHE(name, gb)
|
||||
refills the internal cache from the bitstream
|
||||
after this call at least MIN_CACHE_BITS will be available,
|
||||
|
||||
GET_CACHE(name, gb)
|
||||
will output the contents of the internal cache, next bit is MSB of 32 or 64 bit (FIXME 64bit)
|
||||
|
||||
SHOW_UBITS(name, gb, num)
|
||||
will return the next num bits
|
||||
|
||||
SHOW_SBITS(name, gb, num)
|
||||
will return the next num bits and do sign extension
|
||||
|
||||
SKIP_BITS(name, gb, num)
|
||||
will skip over the next num bits
|
||||
note, this is equivalent to SKIP_CACHE; SKIP_COUNTER
|
||||
|
||||
SKIP_CACHE(name, gb, num)
|
||||
will remove the next num bits from the cache (note SKIP_COUNTER MUST be called before UPDATE_CACHE / CLOSE_READER)
|
||||
|
||||
SKIP_COUNTER(name, gb, num)
|
||||
will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS)
|
||||
|
||||
LAST_SKIP_CACHE(name, gb, num)
|
||||
will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing
|
||||
|
||||
LAST_SKIP_BITS(name, gb, num)
|
||||
is equivalent to SKIP_LAST_CACHE; SKIP_COUNTER
|
||||
|
||||
for examples see get_bits, show_bits, skip_bits, get_vlc
|
||||
*/
|
||||
|
||||
#ifdef ALT_BITSTREAM_READER
|
||||
# define MIN_CACHE_BITS 25
|
||||
|
||||
# define OPEN_READER(name, gb)\
|
||||
int name##_index= (gb)->index;\
|
||||
int name##_cache= 0;\
|
||||
|
||||
# define CLOSE_READER(name, gb)\
|
||||
(gb)->index= name##_index;\
|
||||
|
||||
# ifdef ALT_BITSTREAM_READER_LE
|
||||
# define UPDATE_CACHE(name, gb)\
|
||||
name##_cache= AV_RL32( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) >> (name##_index&0x07);\
|
||||
|
||||
# define SKIP_CACHE(name, gb, num)\
|
||||
name##_cache >>= (num);
|
||||
# else
|
||||
# define UPDATE_CACHE(name, gb)\
|
||||
name##_cache= AV_RB32( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\
|
||||
|
||||
# define SKIP_CACHE(name, gb, num)\
|
||||
name##_cache <<= (num);
|
||||
# endif
|
||||
|
||||
// FIXME name?
|
||||
# define SKIP_COUNTER(name, gb, num)\
|
||||
name##_index += (num);\
|
||||
|
||||
# define SKIP_BITS(name, gb, num)\
|
||||
{\
|
||||
SKIP_CACHE(name, gb, num)\
|
||||
SKIP_COUNTER(name, gb, num)\
|
||||
}\
|
||||
|
||||
# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num)
|
||||
# define LAST_SKIP_CACHE(name, gb, num) ;
|
||||
|
||||
# ifdef ALT_BITSTREAM_READER_LE
|
||||
# define SHOW_UBITS(name, gb, num)\
|
||||
((name##_cache) & (NEG_USR32(0xffffffff,num)))
|
||||
|
||||
# define SHOW_SBITS(name, gb, num)\
|
||||
NEG_SSR32((name##_cache)<<(32-(num)), num)
|
||||
# else
|
||||
# define SHOW_UBITS(name, gb, num)\
|
||||
NEG_USR32(name##_cache, num)
|
||||
|
||||
# define SHOW_SBITS(name, gb, num)\
|
||||
NEG_SSR32(name##_cache, num)
|
||||
# endif
|
||||
|
||||
# define GET_CACHE(name, gb)\
|
||||
((uint32_t)name##_cache)
|
||||
|
||||
static inline int get_bits_count(GetBitContext *s){
|
||||
return s->index;
|
||||
}
|
||||
|
||||
static inline void skip_bits_long(GetBitContext *s, int n){
|
||||
s->index += n;
|
||||
}
|
||||
|
||||
#elif defined LIBMPEG2_BITSTREAM_READER
|
||||
//libmpeg2 like reader
|
||||
|
||||
# define MIN_CACHE_BITS 17
|
||||
|
||||
# define OPEN_READER(name, gb)\
|
||||
int name##_bit_count=(gb)->bit_count;\
|
||||
int name##_cache= (gb)->cache;\
|
||||
uint8_t * name##_buffer_ptr=(gb)->buffer_ptr;\
|
||||
|
||||
# define CLOSE_READER(name, gb)\
|
||||
(gb)->bit_count= name##_bit_count;\
|
||||
(gb)->cache= name##_cache;\
|
||||
(gb)->buffer_ptr= name##_buffer_ptr;\
|
||||
|
||||
# define UPDATE_CACHE(name, gb)\
|
||||
if(name##_bit_count >= 0){\
|
||||
name##_cache+= AV_RB16(name##_buffer_ptr) << name##_bit_count; \
|
||||
name##_buffer_ptr+=2;\
|
||||
name##_bit_count-= 16;\
|
||||
}\
|
||||
|
||||
# define SKIP_CACHE(name, gb, num)\
|
||||
name##_cache <<= (num);\
|
||||
|
||||
# define SKIP_COUNTER(name, gb, num)\
|
||||
name##_bit_count += (num);\
|
||||
|
||||
# define SKIP_BITS(name, gb, num)\
|
||||
{\
|
||||
SKIP_CACHE(name, gb, num)\
|
||||
SKIP_COUNTER(name, gb, num)\
|
||||
}\
|
||||
|
||||
# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num)
|
||||
# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num)
|
||||
|
||||
# define SHOW_UBITS(name, gb, num)\
|
||||
NEG_USR32(name##_cache, num)
|
||||
|
||||
# define SHOW_SBITS(name, gb, num)\
|
||||
NEG_SSR32(name##_cache, num)
|
||||
|
||||
# define GET_CACHE(name, gb)\
|
||||
((uint32_t)name##_cache)
|
||||
|
||||
static inline int get_bits_count(GetBitContext *s){
|
||||
return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count;
|
||||
}
|
||||
|
||||
static inline void skip_bits_long(GetBitContext *s, int n){
|
||||
OPEN_READER(re, s)
|
||||
re_bit_count += n;
|
||||
re_buffer_ptr += 2*(re_bit_count>>4);
|
||||
re_bit_count &= 15;
|
||||
re_cache = ((re_buffer_ptr[-2]<<8) + re_buffer_ptr[-1]) << (16+re_bit_count);
|
||||
UPDATE_CACHE(re, s)
|
||||
CLOSE_READER(re, s)
|
||||
}
|
||||
|
||||
#elif defined A32_BITSTREAM_READER
|
||||
|
||||
# define MIN_CACHE_BITS 32
|
||||
|
||||
# define OPEN_READER(name, gb)\
|
||||
int name##_bit_count=(gb)->bit_count;\
|
||||
uint32_t name##_cache0= (gb)->cache0;\
|
||||
uint32_t name##_cache1= (gb)->cache1;\
|
||||
uint32_t * name##_buffer_ptr=(gb)->buffer_ptr;\
|
||||
|
||||
# define CLOSE_READER(name, gb)\
|
||||
(gb)->bit_count= name##_bit_count;\
|
||||
(gb)->cache0= name##_cache0;\
|
||||
(gb)->cache1= name##_cache1;\
|
||||
(gb)->buffer_ptr= name##_buffer_ptr;\
|
||||
|
||||
# define UPDATE_CACHE(name, gb)\
|
||||
if(name##_bit_count > 0){\
|
||||
const uint32_t next= be2me_32( *name##_buffer_ptr );\
|
||||
name##_cache0 |= NEG_USR32(next,name##_bit_count);\
|
||||
name##_cache1 |= next<<name##_bit_count;\
|
||||
name##_buffer_ptr++;\
|
||||
name##_bit_count-= 32;\
|
||||
}\
|
||||
|
||||
#if defined(ARCH_X86)
|
||||
# define SKIP_CACHE(name, gb, num)\
|
||||
asm(\
|
||||
"shldl %2, %1, %0 \n\t"\
|
||||
"shll %2, %1 \n\t"\
|
||||
: "+r" (name##_cache0), "+r" (name##_cache1)\
|
||||
: "Ic" ((uint8_t)(num))\
|
||||
);
|
||||
#else
|
||||
# define SKIP_CACHE(name, gb, num)\
|
||||
name##_cache0 <<= (num);\
|
||||
name##_cache0 |= NEG_USR32(name##_cache1,num);\
|
||||
name##_cache1 <<= (num);
|
||||
#endif
|
||||
|
||||
# define SKIP_COUNTER(name, gb, num)\
|
||||
name##_bit_count += (num);\
|
||||
|
||||
# define SKIP_BITS(name, gb, num)\
|
||||
{\
|
||||
SKIP_CACHE(name, gb, num)\
|
||||
SKIP_COUNTER(name, gb, num)\
|
||||
}\
|
||||
|
||||
# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num)
|
||||
# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num)
|
||||
|
||||
# define SHOW_UBITS(name, gb, num)\
|
||||
NEG_USR32(name##_cache0, num)
|
||||
|
||||
# define SHOW_SBITS(name, gb, num)\
|
||||
NEG_SSR32(name##_cache0, num)
|
||||
|
||||
# define GET_CACHE(name, gb)\
|
||||
(name##_cache0)
|
||||
|
||||
static inline int get_bits_count(GetBitContext *s){
|
||||
return ((uint8_t*)s->buffer_ptr - s->buffer)*8 - 32 + s->bit_count;
|
||||
}
|
||||
|
||||
static inline void skip_bits_long(GetBitContext *s, int n){
|
||||
OPEN_READER(re, s)
|
||||
re_bit_count += n;
|
||||
re_buffer_ptr += re_bit_count>>5;
|
||||
re_bit_count &= 31;
|
||||
re_cache0 = be2me_32( re_buffer_ptr[-1] ) << re_bit_count;
|
||||
re_cache1 = 0;
|
||||
UPDATE_CACHE(re, s)
|
||||
CLOSE_READER(re, s)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* read mpeg1 dc style vlc (sign bit + mantisse with no MSB).
|
||||
* if MSB not set it is negative
|
||||
* @param n length in bits
|
||||
* @author BERO
|
||||
*/
|
||||
static inline int get_xbits(GetBitContext *s, int n){
|
||||
register int sign;
|
||||
register int32_t cache;
|
||||
OPEN_READER(re, s)
|
||||
UPDATE_CACHE(re, s)
|
||||
cache = GET_CACHE(re,s);
|
||||
sign=(~cache)>>31;
|
||||
LAST_SKIP_BITS(re, s, n)
|
||||
CLOSE_READER(re, s)
|
||||
return (NEG_USR32(sign ^ cache, n) ^ sign) - sign;
|
||||
}
|
||||
|
||||
static inline int get_sbits(GetBitContext *s, int n){
|
||||
register int tmp;
|
||||
OPEN_READER(re, s)
|
||||
UPDATE_CACHE(re, s)
|
||||
tmp= SHOW_SBITS(re, s, n);
|
||||
LAST_SKIP_BITS(re, s, n)
|
||||
CLOSE_READER(re, s)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* reads 1-17 bits.
|
||||
* Note, the alt bitstream reader can read up to 25 bits, but the libmpeg2 reader can't
|
||||
*/
|
||||
static inline unsigned int get_bits(GetBitContext *s, int n){
|
||||
register int tmp;
|
||||
OPEN_READER(re, s)
|
||||
UPDATE_CACHE(re, s)
|
||||
tmp= SHOW_UBITS(re, s, n);
|
||||
LAST_SKIP_BITS(re, s, n)
|
||||
CLOSE_READER(re, s)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* shows 1-17 bits.
|
||||
* Note, the alt bitstream reader can read up to 25 bits, but the libmpeg2 reader can't
|
||||
*/
|
||||
static inline unsigned int show_bits(GetBitContext *s, int n){
|
||||
register int tmp;
|
||||
OPEN_READER(re, s)
|
||||
UPDATE_CACHE(re, s)
|
||||
tmp= SHOW_UBITS(re, s, n);
|
||||
// CLOSE_READER(re, s)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline void skip_bits(GetBitContext *s, int n){
|
||||
//Note gcc seems to optimize this to s->index+=n for the ALT_READER :))
|
||||
OPEN_READER(re, s)
|
||||
UPDATE_CACHE(re, s)
|
||||
LAST_SKIP_BITS(re, s, n)
|
||||
CLOSE_READER(re, s)
|
||||
}
|
||||
|
||||
static inline unsigned int get_bits1(GetBitContext *s){
|
||||
#ifdef ALT_BITSTREAM_READER
|
||||
int index= s->index;
|
||||
uint8_t result= s->buffer[ index>>3 ];
|
||||
#ifdef ALT_BITSTREAM_READER_LE
|
||||
result>>= (index&0x07);
|
||||
result&= 1;
|
||||
#else
|
||||
result<<= (index&0x07);
|
||||
result>>= 8 - 1;
|
||||
#endif
|
||||
index++;
|
||||
s->index= index;
|
||||
|
||||
return result;
|
||||
#else
|
||||
return get_bits(s, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned int show_bits1(GetBitContext *s){
|
||||
return show_bits(s, 1);
|
||||
}
|
||||
|
||||
static inline void skip_bits1(GetBitContext *s){
|
||||
skip_bits(s, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* reads 0-32 bits.
|
||||
*/
|
||||
static inline unsigned int get_bits_long(GetBitContext *s, int n){
|
||||
if(n<=17) return get_bits(s, n);
|
||||
else{
|
||||
#ifdef ALT_BITSTREAM_READER_LE
|
||||
int ret= get_bits(s, 16);
|
||||
return ret | (get_bits(s, n-16) << 16);
|
||||
#else
|
||||
int ret= get_bits(s, 16) << (n-16);
|
||||
return ret | get_bits(s, n-16);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* shows 0-32 bits.
|
||||
*/
|
||||
static inline unsigned int show_bits_long(GetBitContext *s, int n){
|
||||
if(n<=17) return show_bits(s, n);
|
||||
else{
|
||||
GetBitContext gb= *s;
|
||||
int ret= get_bits_long(s, n);
|
||||
*s= gb;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int check_marker(GetBitContext *s, const char *msg)
|
||||
{
|
||||
int bit= get_bits1(s);
|
||||
if(!bit)
|
||||
av_log(NULL, AV_LOG_INFO, "Marker bit missing %s\n", msg);
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* init GetBitContext.
|
||||
* @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes larger then the actual read bits
|
||||
* because some optimized bitstream readers read 32 or 64 bit at once and could read over the end
|
||||
* @param bit_size the size of the buffer in bits
|
||||
*/
|
||||
static inline void init_get_bits(GetBitContext *s,
|
||||
const uint8_t *buffer, int bit_size)
|
||||
{
|
||||
int buffer_size= (bit_size+7)>>3;
|
||||
if(buffer_size < 0 || bit_size < 0) {
|
||||
buffer_size = bit_size = 0;
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
s->buffer= buffer;
|
||||
s->size_in_bits= bit_size;
|
||||
s->buffer_end= buffer + buffer_size;
|
||||
#ifdef ALT_BITSTREAM_READER
|
||||
s->index=0;
|
||||
#elif defined LIBMPEG2_BITSTREAM_READER
|
||||
s->buffer_ptr = (uint8_t*)((intptr_t)buffer&(~1));
|
||||
s->bit_count = 16 + 8*((intptr_t)buffer&1);
|
||||
skip_bits_long(s, 0);
|
||||
#elif defined A32_BITSTREAM_READER
|
||||
s->buffer_ptr = (uint32_t*)((intptr_t)buffer&(~3));
|
||||
s->bit_count = 32 + 8*((intptr_t)buffer&3);
|
||||
skip_bits_long(s, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void align_get_bits(GetBitContext *s)
|
||||
{
|
||||
int n= (-get_bits_count(s)) & 7;
|
||||
if(n) skip_bits(s, n);
|
||||
}
|
||||
|
||||
#define init_vlc(vlc, nb_bits, nb_codes,\
|
||||
bits, bits_wrap, bits_size,\
|
||||
codes, codes_wrap, codes_size,\
|
||||
flags)\
|
||||
init_vlc_sparse(vlc, nb_bits, nb_codes,\
|
||||
bits, bits_wrap, bits_size,\
|
||||
codes, codes_wrap, codes_size,\
|
||||
NULL, 0, 0, flags)
|
||||
|
||||
int init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
|
||||
const void *bits, int bits_wrap, int bits_size,
|
||||
const void *codes, int codes_wrap, int codes_size,
|
||||
const void *symbols, int symbols_wrap, int symbols_size,
|
||||
int flags);
|
||||
#define INIT_VLC_USE_STATIC 1 ///< VERY strongly deprecated and forbidden
|
||||
#define INIT_VLC_LE 2
|
||||
#define INIT_VLC_USE_NEW_STATIC 4
|
||||
void free_vlc(VLC *vlc);
|
||||
|
||||
#define INIT_VLC_STATIC(vlc, bits, a,b,c,d,e,f,g, static_size)\
|
||||
{\
|
||||
static VLC_TYPE table[static_size][2];\
|
||||
(vlc)->table= table;\
|
||||
(vlc)->table_allocated= static_size;\
|
||||
init_vlc(vlc, bits, a,b,c,d,e,f,g, INIT_VLC_USE_NEW_STATIC);\
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* if the vlc code is invalid and max_depth=1 than no bits will be removed
|
||||
* if the vlc code is invalid and max_depth>1 than the number of bits removed
|
||||
* is undefined
|
||||
*/
|
||||
#define GET_VLC(code, name, gb, table, bits, max_depth)\
|
||||
{\
|
||||
int n, index, nb_bits;\
|
||||
\
|
||||
index= SHOW_UBITS(name, gb, bits);\
|
||||
code = table[index][0];\
|
||||
n = table[index][1];\
|
||||
\
|
||||
if(max_depth > 1 && n < 0){\
|
||||
LAST_SKIP_BITS(name, gb, bits)\
|
||||
UPDATE_CACHE(name, gb)\
|
||||
\
|
||||
nb_bits = -n;\
|
||||
\
|
||||
index= SHOW_UBITS(name, gb, nb_bits) + code;\
|
||||
code = table[index][0];\
|
||||
n = table[index][1];\
|
||||
if(max_depth > 2 && n < 0){\
|
||||
LAST_SKIP_BITS(name, gb, nb_bits)\
|
||||
UPDATE_CACHE(name, gb)\
|
||||
\
|
||||
nb_bits = -n;\
|
||||
\
|
||||
index= SHOW_UBITS(name, gb, nb_bits) + code;\
|
||||
code = table[index][0];\
|
||||
n = table[index][1];\
|
||||
}\
|
||||
}\
|
||||
SKIP_BITS(name, gb, n)\
|
||||
}
|
||||
|
||||
#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth, need_update)\
|
||||
{\
|
||||
int n, index, nb_bits;\
|
||||
\
|
||||
index= SHOW_UBITS(name, gb, bits);\
|
||||
level = table[index].level;\
|
||||
n = table[index].len;\
|
||||
\
|
||||
if(max_depth > 1 && n < 0){\
|
||||
SKIP_BITS(name, gb, bits)\
|
||||
if(need_update){\
|
||||
UPDATE_CACHE(name, gb)\
|
||||
}\
|
||||
\
|
||||
nb_bits = -n;\
|
||||
\
|
||||
index= SHOW_UBITS(name, gb, nb_bits) + level;\
|
||||
level = table[index].level;\
|
||||
n = table[index].len;\
|
||||
}\
|
||||
run= table[index].run;\
|
||||
SKIP_BITS(name, gb, n)\
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* parses a vlc code, faster then get_vlc()
|
||||
* @param bits is the number of bits which will be read at once, must be
|
||||
* identical to nb_bits in init_vlc()
|
||||
* @param max_depth is the number of times bits bits must be read to completely
|
||||
* read the longest vlc code
|
||||
* = (max_vlc_length + bits - 1) / bits
|
||||
*/
|
||||
static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2],
|
||||
int bits, int max_depth)
|
||||
{
|
||||
int code;
|
||||
|
||||
OPEN_READER(re, s)
|
||||
UPDATE_CACHE(re, s)
|
||||
|
||||
GET_VLC(code, re, s, table, bits, max_depth)
|
||||
|
||||
CLOSE_READER(re, s)
|
||||
return code;
|
||||
}
|
||||
|
||||
//#define TRACE
|
||||
|
||||
#ifdef TRACE
|
||||
static inline void print_bin(int bits, int n){
|
||||
int i;
|
||||
|
||||
for(i=n-1; i>=0; i--){
|
||||
av_log(NULL, AV_LOG_DEBUG, "%d", (bits>>i)&1);
|
||||
}
|
||||
for(i=n; i<24; i++)
|
||||
av_log(NULL, AV_LOG_DEBUG, " ");
|
||||
}
|
||||
|
||||
static inline int get_bits_trace(GetBitContext *s, int n, char *file, const char *func, int line){
|
||||
int r= get_bits(s, n);
|
||||
|
||||
print_bin(r, n);
|
||||
av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d bit @%5d in %s %s:%d\n", r, n, r, get_bits_count(s)-n, file, func, line);
|
||||
return r;
|
||||
}
|
||||
static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth, char *file, const char *func, int line){
|
||||
int show= show_bits(s, 24);
|
||||
int pos= get_bits_count(s);
|
||||
int r= get_vlc2(s, table, bits, max_depth);
|
||||
int len= get_bits_count(s) - pos;
|
||||
int bits2= show>>(24-len);
|
||||
|
||||
print_bin(bits2, len);
|
||||
|
||||
av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d vlc @%5d in %s %s:%d\n", bits2, len, r, pos, file, func, line);
|
||||
return r;
|
||||
}
|
||||
static inline int get_xbits_trace(GetBitContext *s, int n, char *file, const char *func, int line){
|
||||
int show= show_bits(s, n);
|
||||
int r= get_xbits(s, n);
|
||||
|
||||
print_bin(show, n);
|
||||
av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d xbt @%5d in %s %s:%d\n", show, n, r, get_bits_count(s)-n, file, func, line);
|
||||
return r;
|
||||
}
|
||||
|
||||
#define get_bits(s, n) get_bits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
|
||||
#define tprintf(p, ...) av_log(p, AV_LOG_DEBUG, __VA_ARGS__)
|
||||
|
||||
#else //TRACE
|
||||
#define tprintf(p, ...) {}
|
||||
#endif
|
||||
|
||||
static inline int decode012(GetBitContext *gb){
|
||||
int n;
|
||||
n = get_bits1(gb);
|
||||
if (n == 0)
|
||||
return 0;
|
||||
else
|
||||
return get_bits1(gb) + 1;
|
||||
}
|
||||
|
||||
static inline int decode210(GetBitContext *gb){
|
||||
if (get_bits1(gb))
|
||||
return 0;
|
||||
else
|
||||
return 2 - get_bits1(gb);
|
||||
}
|
||||
|
||||
#endif /* FFMPEG_BITSTREAM_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* 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"
|
||||
|
||||
AVBitStreamFilter *first_bitstream_filter= NULL;
|
||||
|
||||
AVBitStreamFilter *av_bitstream_filter_next(AVBitStreamFilter *f){
|
||||
if(f) return f->next;
|
||||
else return first_bitstream_filter;
|
||||
}
|
||||
|
||||
void av_register_bitstream_filter(AVBitStreamFilter *bsf){
|
||||
bsf->next = first_bitstream_filter;
|
||||
first_bitstream_filter= bsf;
|
||||
}
|
||||
|
||||
AVBitStreamFilterContext *av_bitstream_filter_init(const char *name){
|
||||
AVBitStreamFilter *bsf= first_bitstream_filter;
|
||||
|
||||
while(bsf){
|
||||
if(!strcmp(name, bsf->name)){
|
||||
AVBitStreamFilterContext *bsfc= av_mallocz(sizeof(AVBitStreamFilterContext));
|
||||
bsfc->filter= bsf;
|
||||
bsfc->priv_data= av_mallocz(bsf->priv_data_size);
|
||||
return bsfc;
|
||||
}
|
||||
bsf= bsf->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc){
|
||||
if(bsfc->filter->close)
|
||||
bsfc->filter->close(bsfc);
|
||||
av_freep(&bsfc->priv_data);
|
||||
av_parser_close(bsfc->parser);
|
||||
av_free(bsfc);
|
||||
}
|
||||
|
||||
int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
|
||||
AVCodecContext *avctx, const char *args,
|
||||
uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size, int keyframe){
|
||||
*poutbuf= (uint8_t *) buf;
|
||||
*poutbuf_size= buf_size;
|
||||
return bsfc->filter->filter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, buf_size, keyframe);
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* BMP image format decoder
|
||||
* Copyright (c) 2005 Mans Rullgard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "bmp.h"
|
||||
|
||||
static av_cold int bmp_decode_init(AVCodecContext *avctx){
|
||||
BMPContext *s = avctx->priv_data;
|
||||
|
||||
avcodec_get_frame_defaults((AVFrame*)&s->picture);
|
||||
avctx->coded_frame = (AVFrame*)&s->picture;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bmp_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
BMPContext *s = avctx->priv_data;
|
||||
AVFrame *picture = data;
|
||||
AVFrame *p = &s->picture;
|
||||
unsigned int fsize, hsize;
|
||||
int width, height;
|
||||
unsigned int depth;
|
||||
BiCompression comp;
|
||||
unsigned int ihsize;
|
||||
int i, j, n, linesize;
|
||||
uint32_t rgb[3];
|
||||
uint8_t *ptr;
|
||||
int dsize;
|
||||
const uint8_t *buf0 = buf;
|
||||
|
||||
if(buf_size < 14){
|
||||
av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(bytestream_get_byte(&buf) != 'B' ||
|
||||
bytestream_get_byte(&buf) != 'M') {
|
||||
av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fsize = bytestream_get_le32(&buf);
|
||||
if(buf_size < fsize){
|
||||
av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
|
||||
buf_size, fsize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf += 2; /* reserved1 */
|
||||
buf += 2; /* reserved2 */
|
||||
|
||||
hsize = bytestream_get_le32(&buf); /* header size */
|
||||
if(fsize <= hsize){
|
||||
av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
|
||||
fsize, hsize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ihsize = bytestream_get_le32(&buf); /* more header size */
|
||||
if(ihsize + 14 > hsize){
|
||||
av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ihsize == 40) {
|
||||
width = bytestream_get_le32(&buf);
|
||||
height = bytestream_get_le32(&buf);
|
||||
} else if (ihsize == 12) {
|
||||
width = bytestream_get_le16(&buf);
|
||||
height = bytestream_get_le16(&buf);
|
||||
} else {
|
||||
av_log(avctx, AV_LOG_ERROR, "unsupported BMP file, patch welcome");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(bytestream_get_le16(&buf) != 1){ /* planes */
|
||||
av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
depth = bytestream_get_le16(&buf);
|
||||
|
||||
if(ihsize == 40)
|
||||
comp = bytestream_get_le32(&buf);
|
||||
else
|
||||
comp = BMP_RGB;
|
||||
|
||||
if(comp != BMP_RGB && comp != BMP_BITFIELDS){
|
||||
av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(comp == BMP_BITFIELDS){
|
||||
buf += 20;
|
||||
rgb[0] = bytestream_get_le32(&buf);
|
||||
rgb[1] = bytestream_get_le32(&buf);
|
||||
rgb[2] = bytestream_get_le32(&buf);
|
||||
}
|
||||
|
||||
avctx->width = width;
|
||||
avctx->height = height > 0? height: -height;
|
||||
|
||||
avctx->pix_fmt = PIX_FMT_NONE;
|
||||
|
||||
switch(depth){
|
||||
case 32:
|
||||
if(comp == BMP_BITFIELDS){
|
||||
rgb[0] = (rgb[0] >> 15) & 3;
|
||||
rgb[1] = (rgb[1] >> 15) & 3;
|
||||
rgb[2] = (rgb[2] >> 15) & 3;
|
||||
|
||||
if(rgb[0] + rgb[1] + rgb[2] != 3 ||
|
||||
rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]){
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
rgb[0] = 2;
|
||||
rgb[1] = 1;
|
||||
rgb[2] = 0;
|
||||
}
|
||||
|
||||
avctx->pix_fmt = PIX_FMT_BGR24;
|
||||
break;
|
||||
case 24:
|
||||
avctx->pix_fmt = PIX_FMT_BGR24;
|
||||
break;
|
||||
case 16:
|
||||
if(comp == BMP_RGB)
|
||||
avctx->pix_fmt = PIX_FMT_RGB555;
|
||||
break;
|
||||
default:
|
||||
av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(avctx->pix_fmt == PIX_FMT_NONE){
|
||||
av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(p->data[0])
|
||||
avctx->release_buffer(avctx, p);
|
||||
|
||||
p->reference = 0;
|
||||
if(avctx->get_buffer(avctx, p) < 0){
|
||||
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
p->pict_type = FF_I_TYPE;
|
||||
p->key_frame = 1;
|
||||
|
||||
buf = buf0 + hsize;
|
||||
dsize = buf_size - hsize;
|
||||
|
||||
/* Line size in file multiple of 4 */
|
||||
n = (avctx->width * (depth / 8) + 3) & ~3;
|
||||
|
||||
if(n * avctx->height > dsize){
|
||||
av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
|
||||
dsize, n * avctx->height);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(height > 0){
|
||||
ptr = p->data[0] + (avctx->height - 1) * p->linesize[0];
|
||||
linesize = -p->linesize[0];
|
||||
} else {
|
||||
ptr = p->data[0];
|
||||
linesize = p->linesize[0];
|
||||
}
|
||||
|
||||
switch(depth){
|
||||
case 24:
|
||||
for(i = 0; i < avctx->height; i++){
|
||||
memcpy(ptr, buf, avctx->width*(depth>>3));
|
||||
buf += n;
|
||||
ptr += linesize;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
for(i = 0; i < avctx->height; i++){
|
||||
const uint16_t *src = (const uint16_t *) buf;
|
||||
uint16_t *dst = (uint16_t *) ptr;
|
||||
|
||||
for(j = 0; j < avctx->width; j++)
|
||||
*dst++ = le2me_16(*src++);
|
||||
|
||||
buf += n;
|
||||
ptr += linesize;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
for(i = 0; i < avctx->height; i++){
|
||||
const uint8_t *src = buf;
|
||||
uint8_t *dst = ptr;
|
||||
|
||||
for(j = 0; j < avctx->width; j++){
|
||||
dst[0] = src[rgb[2]];
|
||||
dst[1] = src[rgb[1]];
|
||||
dst[2] = src[rgb[0]];
|
||||
dst += 3;
|
||||
src += 4;
|
||||
}
|
||||
|
||||
buf += n;
|
||||
ptr += linesize;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*picture = s->picture;
|
||||
*data_size = sizeof(AVPicture);
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static av_cold int bmp_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
BMPContext* c = avctx->priv_data;
|
||||
|
||||
if (c->picture.data[0])
|
||||
avctx->release_buffer(avctx, &c->picture);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVCodec bmp_decoder = {
|
||||
"bmp",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_BMP,
|
||||
sizeof(BMPContext),
|
||||
bmp_decode_init,
|
||||
NULL,
|
||||
bmp_decode_end,
|
||||
bmp_decode_frame,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("BMP image"),
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* internals for BMP codecs
|
||||
* Copyright (c) 2005 Mans Rullgard
|
||||
*
|
||||
* 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_BMP_H
|
||||
#define FFMPEG_BMP_H
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
typedef struct BMPContext {
|
||||
AVFrame picture;
|
||||
} BMPContext;
|
||||
|
||||
typedef enum {
|
||||
BMP_RGB =0,
|
||||
BMP_RLE8 =1,
|
||||
BMP_RLE4 =2,
|
||||
BMP_BITFIELDS =3,
|
||||
} BiCompression;
|
||||
|
||||
#endif /* FFMPEG_BMP_H */
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* BMP image format encoder
|
||||
* Copyright (c) 2006, 2007 Michel Bardiaux
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "bmp.h"
|
||||
|
||||
static av_cold int bmp_encode_init(AVCodecContext *avctx){
|
||||
BMPContext *s = avctx->priv_data;
|
||||
|
||||
avcodec_get_frame_defaults((AVFrame*)&s->picture);
|
||||
avctx->coded_frame = (AVFrame*)&s->picture;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bmp_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
|
||||
BMPContext *s = avctx->priv_data;
|
||||
AVFrame *pict = data;
|
||||
AVFrame * const p= (AVFrame*)&s->picture;
|
||||
int n_bytes_image, n_bytes_per_row, n_bytes, i, n, hsize;
|
||||
uint8_t *ptr;
|
||||
unsigned char* buf0 = buf;
|
||||
*p = *pict;
|
||||
p->pict_type= FF_I_TYPE;
|
||||
p->key_frame= 1;
|
||||
n_bytes_per_row = (avctx->width*3 + 3) & ~3;
|
||||
n_bytes_image = avctx->height*n_bytes_per_row;
|
||||
|
||||
// STRUCTURE.field refer to the MSVC documentation for BITMAPFILEHEADER
|
||||
// and related pages.
|
||||
#define SIZE_BITMAPFILEHEADER 14
|
||||
#define SIZE_BITMAPINFOHEADER 40
|
||||
hsize = SIZE_BITMAPFILEHEADER + SIZE_BITMAPINFOHEADER;
|
||||
n_bytes = n_bytes_image + hsize;
|
||||
if(n_bytes>buf_size) {
|
||||
av_log(avctx, AV_LOG_ERROR, "buf size too small (need %d, got %d)\n", n_bytes, buf_size);
|
||||
return -1;
|
||||
}
|
||||
bytestream_put_byte(&buf, 'B'); // BITMAPFILEHEADER.bfType
|
||||
bytestream_put_byte(&buf, 'M'); // do.
|
||||
bytestream_put_le32(&buf, n_bytes); // BITMAPFILEHEADER.bfSize
|
||||
bytestream_put_le16(&buf, 0); // BITMAPFILEHEADER.bfReserved1
|
||||
bytestream_put_le16(&buf, 0); // BITMAPFILEHEADER.bfReserved2
|
||||
bytestream_put_le32(&buf, hsize); // BITMAPFILEHEADER.bfOffBits
|
||||
bytestream_put_le32(&buf, SIZE_BITMAPINFOHEADER); // BITMAPINFOHEADER.biSize
|
||||
bytestream_put_le32(&buf, avctx->width); // BITMAPINFOHEADER.biWidth
|
||||
bytestream_put_le32(&buf, avctx->height); // BITMAPINFOHEADER.biHeight
|
||||
bytestream_put_le16(&buf, 1); // BITMAPINFOHEADER.biPlanes
|
||||
bytestream_put_le16(&buf, 24); // BITMAPINFOHEADER.biBitCount
|
||||
bytestream_put_le32(&buf, BMP_RGB); // BITMAPINFOHEADER.biCompression
|
||||
bytestream_put_le32(&buf, n_bytes_image); // BITMAPINFOHEADER.biSizeImage
|
||||
bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biXPelsPerMeter
|
||||
bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biYPelsPerMeter
|
||||
bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biClrUsed
|
||||
bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biClrImportant
|
||||
// BMP files are bottom-to-top so we start from the end...
|
||||
ptr = p->data[0] + (avctx->height - 1) * p->linesize[0];
|
||||
buf = buf0 + hsize;
|
||||
for(i = 0; i < avctx->height; i++) {
|
||||
n = 3*avctx->width;
|
||||
memcpy(buf, ptr, n);
|
||||
buf += n;
|
||||
memset(buf, 0, n_bytes_per_row-n);
|
||||
buf += n_bytes_per_row-n;
|
||||
ptr -= p->linesize[0]; // ... and go back
|
||||
}
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
AVCodec bmp_encoder = {
|
||||
"bmp",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_BMP,
|
||||
sizeof(BMPContext),
|
||||
bmp_encode_init,
|
||||
bmp_encode_frame,
|
||||
NULL, //encode_end,
|
||||
.pix_fmts= (enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE},
|
||||
.long_name = NULL_IF_CONFIG_SMALL("BMP image"),
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Bytestream functions
|
||||
* copyright (c) 2006 Baptiste Coudurier <[email protected]>
|
||||
*
|
||||
* 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_BYTESTREAM_H
|
||||
#define FFMPEG_BYTESTREAM_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define DEF_T(type, name, bytes, read, write) \
|
||||
static av_always_inline type bytestream_get_ ## name(const uint8_t **b){\
|
||||
(*b) += bytes;\
|
||||
return read(*b - bytes);\
|
||||
}\
|
||||
static av_always_inline void bytestream_put_ ##name(uint8_t **b, const type value){\
|
||||
write(*b, value);\
|
||||
(*b) += bytes;\
|
||||
}
|
||||
|
||||
#define DEF(name, bytes, read, write) \
|
||||
DEF_T(unsigned int, name, bytes, read, write)
|
||||
#define DEF64(name, bytes, read, write) \
|
||||
DEF_T(uint64_t, name, bytes, read, write)
|
||||
|
||||
DEF64(le64, 8, AV_RL64, AV_WL64)
|
||||
DEF (le32, 4, AV_RL32, AV_WL32)
|
||||
DEF (le24, 3, AV_RL24, AV_WL24)
|
||||
DEF (le16, 2, AV_RL16, AV_WL16)
|
||||
DEF64(be64, 8, AV_RB64, AV_WB64)
|
||||
DEF (be32, 4, AV_RB32, AV_WB32)
|
||||
DEF (be24, 3, AV_RB24, AV_WB24)
|
||||
DEF (be16, 2, AV_RB16, AV_WB16)
|
||||
DEF (byte, 1, AV_RB8 , AV_WB8 )
|
||||
|
||||
#undef DEF
|
||||
#undef DEF64
|
||||
#undef DEF_T
|
||||
|
||||
static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
|
||||
{
|
||||
memcpy(dst, *b, size);
|
||||
(*b) += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
|
||||
{
|
||||
memcpy(*b, src, size);
|
||||
(*b) += size;
|
||||
}
|
||||
|
||||
#endif /* FFMPEG_BYTESTREAM_H */
|
||||
Reference in New Issue
Block a user