Commit 950c5030 authored by Donald Haase's avatar Donald Haase
Browse files

Initial commit from dcdivx_b4.zip

parents
/*This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
* *
* *
* Authors: *
* Marc Dukette
* Jacob Alberty
**************************************************************************************/
#include <stdarg.h>
#include <stdio.h>
#include "divx.h"
#include "sintab.h"
/* Some misc 3D utils */
/* Rotate a 3-pair of coordinates by the given angle 0..255 */
void rotate(int zang, int xang, int yang, float *x, float *y, float *z) {
float tx, ty, tz;
tx = (mcos(zang)* *x - msin(zang)* *y);
ty = (mcos(zang)* *y + msin(zang)* *x);
*x = tx; *y = ty;
tz = (mcos(xang)* *z - msin(xang)* *y);
ty = (mcos(xang)* *y + msin(xang)* *z);
*y = ty; *z = tz;
tx = (mcos(yang)* *x - msin(yang)* *z);
tz = (mcos(yang)* *z + msin(yang)* *x);
*x = tx; *z = tz;
}
/* Draw the mouse cursor at the given location */
void draw_poly_mouse(int ptrx, int ptry) {
poly_hdr_t poly;
vertex_ot_t vert;
/* Start a textured polygon set (with the font texture) */
ta_poly_hdr_txr(&poly, TA_TRANSLUCENT, TA_ARGB4444, 256, 256,
util_texture, TA_NO_FILTER);
ta_commit_poly_hdr(&poly);
vert.flags = TA_VERTEX_NORMAL;
vert.x = ptrx;
vert.y = ptry + 16.0f;
vert.z = 512.0f;
vert.u = 0.0f;
vert.v = 16.0f / 256.0f;
vert.dummy1 = vert.dummy2 = 0;
vert.a = 0.80f;
vert.r = 1.0f;
vert.g = 1.0f;
vert.b = 1.0f;
vert.oa = vert.or = vert.og = vert.ob = 0.0f;
ta_commit_vertex(&vert, sizeof(vert));
vert.x = ptrx;
vert.y = ptry;
vert.u = 0.0f;
vert.v = 0.0f;
ta_commit_vertex(&vert, sizeof(vert));
vert.x = ptrx + 10.0f;
vert.y = ptry + 16.0f;
vert.u = 10.0f / 256.0f;
vert.v = 16.0f / 256.0f;
ta_commit_vertex(&vert, sizeof(vert));
vert.flags = TA_VERTEX_EOL;
vert.x = ptrx + 10.0f;
vert.y = ptry;
vert.u = 10.0f / 256.0f;
vert.v = 0.0f;
ta_commit_vertex(&vert, sizeof(vert));
}
/* Draw one font character (12x24); assumes polygon header already sent */
void draw_poly_char(float x1, float y1, float z1, float a, float r, float g, float b, int c) {
vertex_ot_t vert;
int ix = (c % 16) * 16;
int iy = (c / 16) * 24;
float u1 = ix * 1.0f / 256.0f;
float v1 = iy * 1.0f / 256.0f;
float u2 = (ix+12) * 1.0f / 256.0f;
float v2 = (iy+24) * 1.0f / 256.0f;
vert.flags = TA_VERTEX_NORMAL;
vert.x = x1;
vert.y = y1 + 24.0f;
vert.z = z1;
vert.u = u1;
vert.v = v2;
vert.dummy1 = vert.dummy2 = 0;
vert.a = a;
vert.r = r;
vert.g = g;
vert.b = b;
vert.oa = vert.or = vert.og = vert.ob = 0.0f;
ta_commit_vertex(&vert, sizeof(vert));
vert.x = x1;
vert.y = y1;
vert.u = u1;
vert.v = v1;
ta_commit_vertex(&vert, sizeof(vert));
vert.x = x1 + 12.0f;
vert.y = y1 + 24.0f;
vert.u = u2;
vert.v = v2;
ta_commit_vertex(&vert, sizeof(vert));
vert.flags = TA_VERTEX_EOL;
vert.x = x1 + 12.0f;
vert.y = y1;
vert.u = u2;
vert.v = v1;
ta_commit_vertex(&vert, sizeof(vert));
}
/* Draw a set of textured polygons at the given depth and color that
represent a string of text. */
static char strbuf[1024];
void draw_poly_strf(float x1, float y1, float z1, float a, float r,
float g, float b, char *fmt, ...) {
va_list args;
char *s;
poly_hdr_t poly;
va_start(args, fmt);
vsprintf(strbuf, fmt, args);
va_end(args);
ta_poly_hdr_txr(&poly, TA_TRANSLUCENT, TA_ARGB4444, 256, 256, util_texture, TA_NO_FILTER);
ta_commit_poly_hdr(&poly);
s = strbuf;
while (*s) {
if (*s == ' ') {
x1 += 12.0f; s++;
} else {
draw_poly_char(x1+=12.0f, y1, z1, a, r, g, b, *s++);
}
}
}
/* Draw a polygon for a shaded box; wow, a nasty looking func =) */
void draw_poly_box(float x1, float y1, float x2, float y2, float z,
float a1, float r1, float g1, float b1,
float a2, float r2, float g2, float b2) {
poly_hdr_t poly;
vertex_oc_t vert;
ta_poly_hdr_col(&poly, TA_TRANSLUCENT);
ta_commit_poly_hdr(&poly);
vert.flags = TA_VERTEX_NORMAL;
vert.x = x1; vert.y = y2; vert.z = z;
vert.a = (a1+a2)/2; vert.r = (r1+r2/2); vert.g = (g1+g2)/2; vert.b = (b1+b2)/2;
ta_commit_vertex(&vert, sizeof(vert));
vert.y = y1;
vert.a = a1; vert.r = r1; vert.g = g1; vert.b = b1;
ta_commit_vertex(&vert, sizeof(vert));
vert.x = x2; vert.y = y2;
vert.a = a2; vert.r = r2; vert.g = g2; vert.b = b2;
ta_commit_vertex(&vert, sizeof(vert));
vert.flags = TA_VERTEX_EOL;
vert.y = y1;
vert.a = (a1+a2)/2; vert.r = (r1+r2/2); vert.g = (g1+g2)/2; vert.b = (b1+b2)/2;
ta_commit_vertex(&vert, sizeof(vert));
}
/*This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
* *
* *
* Authors: *
* Marc Dukette
**************************************************************************************/
#include "kos.h"
#include "AVIDecaps.h"
#include "inputmedia.h"
videoinfo thisvid;
char data[256];
//#include "inputmedia.h"
/*
* Some useful functions
*/
/*
* copy n into dst as a 4 byte,
* little endian number.
* should also work on
* big endian machines
*
*/
int nMalloc=0;
int abytes_read=0;
static void long2str(char *dst, int n)
{
dst[0] = (n ) & 0xff;
dst[1] = (n >> 8) & 0xff;
dst[2] = (n >> 16) & 0xff;
dst[3] = (n >> 24) & 0xff;
}
/* Convert a string of 4
* or 2 bytes to a number,
* also working on big
* endian machines
*
*/
unsigned long str2ulong(char *str)
{
unsigned long result;
result = ( ((unsigned long) str[0] & 0xFF) | ( ((unsigned long)str[1] &0xFF) << 8) |
(((unsigned long) str[2] & 0xFF) << 16) | ( ((unsigned long) str[3] & 0xFF) << 24) );
return result;
}
static unsigned long str2ushort(char *str)
{
return ( str[0] | (str[1]<<8) );
}
/*
* Reads the first 12 bytes of
* the file, and returns TRUE
* if the file is an AVI.
*
*/
int AVIDecaps_IsAVI()
{
//char data[24];
// if(thisvid.input != NULL) {
if( InputMediaRead(data, 12) != 12 ) {
//MessageBox(NULL, "Error Reading", "Info", MB_OK);
return 0;
}
if( strncmp(data, "RIFF", 4) !=0 ||
strncmp(data + 8, "AVI ", 4) !=0 ) {
return 0;
}
return 1;
return 0;
}
/*
* Fill the class with info from headers
* and reconstruct an index if wanted.
*
*/
int AVIDecaps_FillHeader(int getIndex)
{
unsigned long i, n, rate;
char *hdrl_data;
long hdrl_len = 0;
int scale,lasttag = 0;
int vids_strh_seen = 0;
int vids_strf_seen = 0;
int auds_strh_seen = 0;
int auds_strf_seen = 0;
int num_stream = 0;
// char data[256];
/* go through the AVI file and
* extract the header list,
* the start position of the 'movi'
* list and an optionally
* present idx1 tag
*
*/
hdrl_data = 0;
while(1)
{
if( InputMediaRead(data, 8) != 8 )
break;
/*
* we assume it's EOF
*
*/
n = str2ulong(data + 4);
n = PAD_EVEN(n);
if(strncmp(data, "LIST", 4) == 0)
{
if( InputMediaRead(data, 4) != 4 ) {
return 0;
}
n -= 4;
if(strncmp(data, "hdrl", 4) == 0)
{
hdrl_len = n;
if (hdrl_data) free(hdrl_data);
hdrl_data = (char *) malloc(n);
if(hdrl_data == 0) {
return 0;
}
if( InputMediaRead(hdrl_data, n) != n ) {
return 0;
}
}
else if(strncmp(data, "movi", 4) == 0)
{
thisvid.movi_start = InputMediaSeek(0, INPUT_SEEK_CUR);
//break;
InputMediaSeek(n, INPUT_SEEK_CUR);
}
else
{
InputMediaSeek(n, INPUT_SEEK_CUR);
//break;
}
}
else if(strncmp(data,"idx1",4) == 0)
{
thisvid.audio_bytes=0;
unsigned long read;
thisvid.n_idx = thisvid.max_idx = n/16;
for (i=0;i<(thisvid.n_idx/1000)+1;i++)
{
char temp[16000];
int toread=16000;
int i2;
if (i==(thisvid.n_idx/1000))
toread=(thisvid.n_idx%1000)*16;
if( (read = InputMediaRead((char *) temp, toread)) != toread) {
break;
}
for (i2=0;i2<read/16;i2++)
{
if(strncmp(temp+(16*i2)+2, "wb", 2) == 0)
{
thisvid.audio_bytes += str2ulong(temp+(16*i2)+12);
}
}
}
}
else {
InputMediaSeek(n, INPUT_SEEK_CUR);
}
}
if(!hdrl_data) {
return 0;
}
if(!thisvid.movi_start) {
return 0;
}
/*
* interpret the header list
*
*/
for(i=0; i < hdrl_len; )
{
/*
* list tags are completly ignored
*
*/
if(strncmp(hdrl_data + i, "LIST", 4)==0)
{
i+= 12;
continue;
}
n = str2ulong(hdrl_data+i+4);
n = PAD_EVEN(n);
/*
* interpret the tag and its args
*
*/
if(strncmp(hdrl_data + i, "strh", 4)==0)
{
i += 8;
if(strncmp(hdrl_data + i, "vids", 4) == 0 && !vids_strh_seen)
{
memcpy(thisvid.compressor,hdrl_data+i+4,4);
thisvid.compressor[4] = 0;
scale = str2ulong(hdrl_data+i+20);
rate = str2ulong(hdrl_data+i+24);
if(scale!=0)
thisvid.fps = (double)rate/(double)scale;
thisvid.video_frames = str2ulong(hdrl_data+i+32);
thisvid.video_strn = num_stream;
vids_strh_seen = 1;
lasttag = 1;
}
else if (strncmp (hdrl_data + i, "auds", 4) == 0 && ! auds_strh_seen)
{
//thisvid.audio_bytes = str2ulong(hdrl_data + i + 32);//AVIDecaps_SampleSize();
thisvid.audio_strn = num_stream;
auds_strh_seen = 1;
lasttag = 2;
}
else
lasttag = 0;
num_stream++;
}
else if(strncmp(hdrl_data + i, "strf", 4)==0)
{
i += 8;
if(lasttag == 1)
{
/*
* keep a copy of
* the bitmapinfoheader
*
*/
thisvid.width = str2ulong(hdrl_data+i+4);
thisvid.height = str2ulong(hdrl_data+i+8);
vids_strf_seen = 1;
}
else if(lasttag == 2)
{
thisvid.a_fmt = str2ushort(hdrl_data + i );
}
lasttag = 0;
}
else
{
i += 8;
lasttag = 0;
}
i += n;
}
if (hdrl_data) free(hdrl_data);
hdrl_data=0;
if(!vids_strh_seen || !vids_strf_seen || thisvid.video_frames==0) {
return 0;
}
thisvid.video_tag[0] = thisvid.video_strn/10 + '0';
thisvid.video_tag[1] = thisvid.video_strn%10 + '0';
thisvid.video_tag[2] = 'd';
thisvid.video_tag[3] = 'b';
/*
* audio tag is set to "99wb"
* if no audio present
*
*/
thisvid.audio_tag[0] = thisvid.audio_strn/10 + '0';
thisvid.audio_tag[1] = thisvid.audio_strn%10 + '0';
thisvid.audio_tag[2] = 'w';
thisvid.audio_tag[3] = 'b';
//InputMediaSeek(thisvid.movi_start, INPUT_SEEK_SET);
thisvid.currentchunk.pos=thisvid.movi_start;
thisvid.currentchunk.len=0;
thisvid.currentframe.pos=thisvid.movi_start;
thisvid.currentframe.len=0;
/*
* reposition the file
*
*/
//InputMediaSeek(0,
// INPUT_SEEK_SET);
InputMediaClose();
//InputMediaOpen(thisvid.m_lpFilename,INPUT_OPEN_BINARY,thisvid.m_type,2000000);
InputMediaOpen(thisvid.m_lpFilename, 0, 0,2000000,1);
InputMediaSeek(thisvid.movi_start,
INPUT_SEEK_SET);
thisvid.video_pos = 0;
return 1;
}
/*
* Tries to open an AVI
* with and without an index
*/
int AVIDecaps_Open(char* lpFilename, int type, int size,videoinfo** vid)
{
int ret=0;
strcpy(thisvid.m_lpFilename,lpFilename);
thisvid.m_type=type;
if (!InputMediaOpen(lpFilename, 0, type,2000000,0))
{
return 0;
}
thisvid.video_pos = 0;
thisvid.audio_posc = 0;
thisvid.audio_posb = 0;
thisvid.idx = NULL;
thisvid.video_index = NULL;
thisvid.audio_index = NULL;
if(AVIDecaps_IsAVI()) {
if(AVIDecaps_FillHeader(1)) {
ret= 1;
}
else {
InputMediaSeek(0, INPUT_SEEK_SET);
AVIDecaps_IsAVI();
if(AVIDecaps_FillHeader(0)) {
ret=1;
}
}
}
*vid=&::thisvid;
return ret;
}
void GetNextChunkInfo()
{
unsigned long n;
long hdrl_len = 0;
int lasttag = 0;
int vids_strh_seen = 0;
int vids_strf_seen = 0;
int auds_strh_seen = 0;
int auds_strf_seen = 0;
int num_stream = 0;
InputMediaSeek(PAD_EVEN(thisvid.currentchunk.pos+thisvid.currentchunk.len),INPUT_SEEK_SET);
while(1)
{
if( InputMediaRead(data, 8) != 8 )
{
thisvid.currentchunk.pos+=thisvid.currentchunk.len;
thisvid.currentchunk.len=0;
break;
}
n = str2ulong(data + 4);
/*
* the movi list may contain sub-lists,
* ignore them
*
*/
if(strncmp(data,"LIST", 4) == 0)
{
InputMediaSeek(4, INPUT_SEEK_CUR);
continue;
}
/*
* check if we got a tag ##db,
* ##dc or ##wb
*
*/
if( ( (data[2]=='d' || data[2]=='D') &&
(data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) ||
( (data[2]=='w' || data[2]=='W') &&
(data[3]=='b' || data[3]=='B') ) )
{
if(strncmp(data, thisvid.audio_tag, 4) == 0)
{
thisvid.currentchunk.pos = InputMediaSeek(0, INPUT_SEEK_CUR);
thisvid.currentchunk.len = n;
return;
}
}
InputMediaSeek(PAD_EVEN(n),
INPUT_SEEK_CUR);
}
}
void GetNextFrameInfo()
{
unsigned long n;
long hdrl_len = 0;
int lasttag = 0;
int vids_strh_seen = 0;
int vids_strf_seen = 0;
int auds_strh_seen = 0;
int auds_strf_seen = 0;
int num_stream = 0;
char data[256];
InputMediaSeek(PAD_EVEN(thisvid.currentframe.pos+thisvid.currentframe.len),INPUT_SEEK_SET);
while(1)
{
if( InputMediaRead(data, 8) != 8 )
break;
n = str2ulong(data + 4);
/*
* the movi list may contain sub-lists,
* ignore them
*
*/
if(strncmp(data,"LIST", 4) == 0)
{
InputMediaSeek(4, INPUT_SEEK_CUR);
continue;
}
/*
* check if we got a tag ##db,
* ##dc or ##wb
*
*/
if( ( (data[2]=='d' || data[2]=='D') &&
(data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) ||
( (data[2]=='w' || data[2]=='W') &&
(data[3]=='b' || data[3]=='B') ) )
{
if(strncmp(data, thisvid.video_tag, 3) == 0)
{
thisvid.currentframe.flags = 0;//str2ulong(thisvid.idx[i]+ 4);
thisvid.currentframe.pos = InputMediaSeek(0, INPUT_SEEK_CUR);
thisvid.currentframe.len = n;
return;
}
}
InputMediaSeek(PAD_EVEN(n),
INPUT_SEEK_CUR);
}
}
/*
* Returns the wavefromatex
* associated with the first audio
* stream.
*/
/*
* Reads the next video Frame into
* buffer, return the actual size of
* the frame.
*
*/
int AVIDecaps_NextVideoFrame(char *buffer, int drop)
{
//unsigned int n;
//if(thisvid.video_pos >= thisvid.video_frames) {
//
// return -2;
//}
/*
* Request the mutex
* for reading the file;
*/
GetNextFrameInfo();
//n = thisvid.video_index[thisvid.video_pos].len;
InputMediaSeek(thisvid.currentframe.pos, INPUT_SEEK_SET);
InputMediaRead(buffer, thisvid.currentframe.len);
thisvid.video_pos++;
/*
* Release the Mutex.
*/
return thisvid.currentframe.len;
}
/*
* Reads any amount of audio
* data. FIXME : should return
* the actual number read.
*/
int AVIDecaps_ReadAudio(char *audbuf, int bytes)
{
int nr, left = 0, todo;
nr = 0;
/*
* Request the read Mutex
*/
/*
* We loop until we parsed enough
* chunks for the amount we want
*
*/
while(bytes > 0)
{
left = thisvid.currentchunk.len - thisvid.audio_posb;
if(!left)
{
//if(thisvid.audio_posc>=thisvid.audio_chunks-1)
//{
// ReleaseMutex(thisvid.hIOMutex);
// return nr;
// }
//thisvid.audio_posc++;
thisvid.audio_posb = 0;
GetNextChunkInfo();
if (!thisvid.currentchunk.len)
{
return nr;
}
continue;
}
if(bytes<left)
todo = bytes;
else
todo = left;
InputMediaSeek(thisvid.currentchunk.pos + thisvid.audio_posb, INPUT_SEEK_SET);
InputMediaRead(audbuf + nr, todo);
bytes -= todo;
nr += todo;
thisvid.audio_posb += todo;
}
/*
* And release the Mutex.
*/
abytes_read+=nr;
return nr;
}
/*
* Return the actual framerate
* FIXME : should be a double...
*
*/
double AVIDecaps_FrameRate()
{
/*
* Fix for some trailers
*/
if(thisvid.fps == 0)
thisvid.fps = 25;
if(thisvid.fps == 23)
thisvid.fps = 25;
return (double) thisvid.fps;
}
/*
* Seek to a particular
* video frame.
*/
int AVIDecaps_Seek(int percent)
{
return thisvid.audio_bytes;
}
int AVIDecaps_ReSeekAudio()
{
double ratio;
char temp[512];
int nShouldbe;
// nShouldbe=0;
nShouldbe=(abytes_read*(int64)thisvid.video_frames)/thisvid.audio_bytes+1;
while(nShouldbe<thisvid.video_pos)
{
AVIDecaps_ReadAudio(temp,512);
nShouldbe=(abytes_read*(int64)thisvid.video_frames)/thisvid.audio_bytes+1;
}
return thisvid.audio_bytes-abytes_read;
}
double AVIDecaps_GetProgress()
{
return (double) ((double)(thisvid.video_pos))*100.0/((double)thisvid.video_frames);
}
int AVIDecaps_Close()
{
InputMediaClose();
return 1;
}
void InitializeReaderAVI(reader* rd)
{
rd->READER_Open=AVIDecaps_Open;
rd->READER_ReadAudio=AVIDecaps_ReadAudio;
rd->READER_NextVideoFrame=AVIDecaps_NextVideoFrame;
rd->READER_Seek=AVIDecaps_Seek;
rd->READER_ReSeekAudio=AVIDecaps_ReSeekAudio;
rd->READER_GetProgress=AVIDecaps_GetProgress;
rd->READER_Close=AVIDecaps_Close;
}
/*This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
* *
* *
* Authors: *
* Marc Dukette
**************************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef AVI_DECAPS_H
#define AVI_DECAPS_H
/*
* includes
*/
#include <malloc.h>
#include <stdlib.h>
/*
* SOME USEFUL MACROS
*/
//#define AVI_MAX_LEN 2000000000
//#define HEADERBYTES 2048
#define PAD_EVEN(x) ( ((x)+1) & ~1 )
#define AVIIF_KEYFRAME 0x00000010L
/*
* INDEX TYPES
*/
typedef struct
{
long pos;
long len;
char flags;
} video_index_entry;
typedef struct
{
long pos;
long len;
long tot;
} audio_index_entry;
//enum {
//
// INPUT_TYPE_FILE,INPUT_TYPE_CACHEFILE,
// INPUT_TYPE_HTTP
//};
/*
* File mode enum
*/
//enum {
// INPUT_OPEN_ASCII,
// INPUT_OPEN_BINARY
//};
/*
* Seek Enum
*/
enum {
INPUT_SEEK_SET,
INPUT_SEEK_CUR,
INPUT_SEEK_END
};
/*
* Main Class
*/
typedef struct _videoinfo
{
long width;
long height;
double fps;
char compressor[8];
long video_strn;
long video_frames;
char video_tag[4];
long video_pos;
long a_fmt;
// long a_chans;
// long a_rate;
// long a_bits;
long audio_strn;
long audio_bytes;
long audio_chunks;
char audio_tag[4];
long audio_posc;
long audio_posb;
long pos;
long n_idx;
long max_idx;
char (*idx)[16];
video_index_entry *video_index;
audio_index_entry *audio_index;
long last_pos;
long last_len;
long movi_start;
//HANDLE hIOMutex;
char m_lpFilename[200];
int m_type;
int threshhold;
video_index_entry currentframe;
audio_index_entry currentchunk;
} videoinfo;
typedef int (*pREADER_Open)(char* lpFilename, int type, int maxsize,videoinfo** info);
typedef int (*pREADER_ReadAudio)(char *audbuf, int bytes);
typedef int (*pREADER_NextVideoFrame)(char *buffer, int drop);
typedef int (*pREADER_Seek)(int percent);
typedef int (*pREADER_ReSeekAudio)();
typedef double (*pREADER_GetProgress)();
typedef int (*pREADER_Close)();
typedef struct _reader
{
pREADER_Open READER_Open;
pREADER_ReadAudio READER_ReadAudio;
pREADER_NextVideoFrame READER_NextVideoFrame;
pREADER_Seek READER_Seek;
pREADER_ReSeekAudio READER_ReSeekAudio;
pREADER_GetProgress READER_GetProgress;
pREADER_Close READER_Close;
}reader;
int AVIDecaps_IsAVI();
int AVIDecaps_FillHeader(int getIndex);
int AVIDecaps_AddIndexEntry(char *tag,
long flags,
long pos,
long len);
int AVIDecaps_isKeyframe(long frame);
int AVIDecaps_ReadAudio(char *audbuf, int bytes);
int AVIDecaps_Open(char* lpFilename, int Cache, int CacheSize,videoinfo** vidinfo);
double AVIDecaps_FrameRate();
int AVIDecaps_NextVideoFrame(char *buffer, int drop);
int AVIDecaps_VideoSeek(long frame);
int AVIDecaps_AudioSeek(long bytes);
int AVIDecaps_NextKeyFrame();
int AVIDecaps_PreviousKeyFrame();
int AVIDecaps_Seek(int percent);
int AVIDecaps_ReSeekAudio();
// int AVIDecaps_SampleSize();
int AVIDecaps_Rewind();
double AVIDecaps_GetProgress();
int AVIDecaps_Close();
void InitializeReaderAVI(reader* rd);
void InitializeReaderMP3(reader* rd);
#endif
#ifdef __cplusplus
}
#endif
/**************************************************************************************
* *
* This application contains code from OpenDivX and is released as a "Larger Work" *
* under that license. Consistant with that license, this application is released *
* under the GNU General Public License. *
* *
* The OpenDivX license can be found at: http://www.projectmayo.com/opendivx/docs.php *
* The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
* *
* *
* Authors: Damien Chavarria *
* DivX Advanced Research Center <darc at projectmayo.com> *
* Marc Dukette *
**************************************************************************************/
#include "AviDecaps.h"
#include "inputmedia.h"
int CacheSize;
videoinfo thisvid;
/* Convert a string of 4
* or 2 bytes to a number,
* also working on big
* endian machines
*
*/
unsigned long str2ulong(char *str)
{
unsigned long result;
result = ( ((unsigned long) str[0] & 0xFF) | ( ((unsigned long)str[1] &0xFF) << 8) |
(((unsigned long) str[2] & 0xFF) << 16) | ( ((unsigned long) str[3] & 0xFF) << 24) );
return result;
}
static unsigned long str2ushort(char *str)
{
return ( str[0] | (str[1]<<8) );
}
/*
* Reads the first 12 bytes of
* the file, and returns TRUE
* if the file is an AVI.
*
*/
int AVIDecaps_IsAVI()
{
char data[24];
if( InputMediaRead(data, 12) != 12 ) {
return 0;
}
if( strncmp(data, "RIFF", 4) !=0 ||
strncmp(data + 8, "AVI ", 4) !=0 ) {
return 0;
}
return 1;
return 0;
}
/*
* Fill the class with info from headers
* and reconstruct an index if wanted.
*
*/
int AVIDecaps_FillHeader(int getIndex)
{
unsigned long i, n, rate;
long scale, idx_type;
char *hdrl_data;
long hdrl_len = 0;
long nvi=0, nai=0, ioff;
long tot=0;
int lasttag = 0;
int vids_strh_seen = 0;
int auds_strh_seen = 0;
int num_stream = 0;
char data[256];
/* go through the AVI file and
* extract the header list,
* the start position of the 'movi'
* list and an optionally
* present idx1 tag
*
*/
hdrl_data = 0;
while(1)
{
if( InputMediaRead(data, 8) != 8 )
break;
/*
* we assume it's EOF
*
*/
n = str2ulong(data + 4);
n = PAD_EVEN(n);
if(strncmp(data, "LIST", 4) == 0)
{
if( InputMediaRead(data, 4) != 4 ) {
return 0;
}
n -= 4;
if(strncmp(data, "hdrl", 4) == 0)
{
hdrl_len = n;
if (hdrl_data) free(hdrl_data);
hdrl_data = (char *) malloc(n);
if(hdrl_data == 0) {
return 0;
}
if( InputMediaRead(hdrl_data, n) != n ) {
return 0;
}
}
else if(strncmp(data, "movi", 4) == 0)
{
thisvid.movi_start = InputMediaSeek(0, INPUT_SEEK_CUR);
InputMediaSeek(n, INPUT_SEEK_CUR);
}
else
InputMediaSeek(n, INPUT_SEEK_CUR);
}
else if(strncmp(data,"idx1",4) == 0)
{
thisvid.n_idx = thisvid.max_idx = n/16;
if (thisvid.idx) free(thisvid.idx);
thisvid.video_index = (video_index_entry *) malloc(100000*sizeof(video_index_entry));
if (!thisvid.video_index)
{
return 0;
}
thisvid.audio_index = (audio_index_entry *) malloc(100000*sizeof(audio_index_entry));
if (!thisvid.audio_index)
{
free(thisvid.video_index);
thisvid.video_index=0;
return 0;
}
tot=0;
unsigned long read;
ioff = thisvid.movi_start+4;
for (i=0;i<(thisvid.n_idx/1000)+1;i++)
{
char temp[16000];
int toread=16000;
int i2;
if (i==(thisvid.n_idx/1000))
toread=(thisvid.n_idx%1000)*16;
if( (read = InputMediaRead((char *) temp, toread)) != toread) {
break;
}
for (i2=0;i2<read/16;i2++)
{
if(strncmp(temp+(16*i2)+2, "db", 1) == 0)
{
if(nvi%100000==0)
{
void* ptr = realloc((void *)thisvid.video_index,
(nvi+100000)*sizeof(video_index_entry));
if (!ptr)
{
free(thisvid.video_index);
thisvid.video_index=0;
free(thisvid.audio_index);
thisvid.audio_index=0;
return 0;
}
thisvid.video_index = (video_index_entry*)ptr;
}
thisvid.video_index[nvi].flags = (char) (str2ulong(temp+(16*i2) +4) & AVIIF_KEYFRAME)>1;
thisvid.video_index[nvi].pos = str2ulong(temp+(16*i2)+ 8)+ioff;
thisvid.video_index[nvi].len = str2ulong(temp+(16*i2)+12);
nvi++;
}
else if(strncmp(temp+(16*i2)+2, "wb", 2) == 0)
{
if(nai%100000==0)
{
void* ptr = realloc((void *)thisvid.audio_index,
(nai+100000)*sizeof(audio_index_entry));
if (!ptr)
{
free(thisvid.video_index);
thisvid.video_index=0;
free(thisvid.audio_index);
thisvid.audio_index=0;
return 0;
}
thisvid.audio_index = (audio_index_entry*)ptr;
}
thisvid.audio_index[nai].pos = str2ulong(temp+(16*i2)+ 8)+ioff;
thisvid.audio_index[nai].len = str2ulong(temp+(16*i2)+12);
thisvid.audio_index[nai].tot = tot;
tot += thisvid.audio_index[nai].len;
nai++;
}
}
}
void* ptr = realloc((void *)thisvid.video_index,
(nvi)*sizeof(video_index_entry));
thisvid.video_index = (video_index_entry*)ptr;
ptr = realloc((void *)thisvid.audio_index,
(nai)*sizeof(audio_index_entry));
thisvid.audio_index = (audio_index_entry*)ptr;
}
else {
InputMediaSeek(n, INPUT_SEEK_CUR);
}
}
/*
* interpret the header list
*
*/
for(i=0; i < hdrl_len; )
{
/*
* list tags are completly ignored
*
*/
if(strncmp(hdrl_data + i, "LIST", 4)==0)
{
i+= 12;
continue;
}
n = str2ulong(hdrl_data+i+4);
n = PAD_EVEN(n);
/*
* interpret the tag and its args
*
*/
if(strncmp(hdrl_data + i, "strh", 4)==0)
{
i += 8;
if(strncmp(hdrl_data + i, "vids", 4) == 0 && !vids_strh_seen)
{
memcpy(thisvid.compressor,hdrl_data+i+4,4);
thisvid.compressor[4] = 0;
scale = str2ulong(hdrl_data+i+20);
rate = str2ulong(hdrl_data+i+24);
if(scale!=0)
thisvid.fps = (double)rate/(double)scale;
thisvid.video_frames = str2ulong(hdrl_data+i+32);
thisvid.video_strn = num_stream;
vids_strh_seen = 1;
lasttag = 1;
}
else if (strncmp (hdrl_data + i, "auds", 4) == 0 && ! auds_strh_seen)
{
thisvid.audio_bytes = str2ulong(hdrl_data + i + 32); //*AVIDecaps_SampleSize();
thisvid.audio_strn = num_stream;
auds_strh_seen = 1;
lasttag = 2;
}
else
lasttag = 0;
num_stream++;
}
else if(strncmp(hdrl_data + i, "strf", 4)==0)
{
i += 8;
if(lasttag == 1)
{
thisvid.width = str2ulong(hdrl_data+i+4);
thisvid.height = str2ulong(hdrl_data+i+8);
}
else if(lasttag == 2)
{
thisvid.a_fmt = str2ushort(hdrl_data + i );
}
lasttag = 0;
}
else
{
i += 8;
lasttag = 0;
}
i += n;
}
if (hdrl_data)
free(hdrl_data);
hdrl_data=0;
thisvid.video_tag[0] = thisvid.video_strn/10 + '0';
thisvid.video_tag[1] = thisvid.video_strn%10 + '0';
thisvid.video_tag[2] = 'd';
thisvid.video_tag[3] = 'b';
thisvid.audio_tag[0] = thisvid.audio_strn/10 + '0';
thisvid.audio_tag[1] = thisvid.audio_strn%10 + '0';
thisvid.audio_tag[2] = 'w';
thisvid.audio_tag[3] = 'b';
//InputMediaSeek(thisvid.movi_start, INPUT_SEEK_SET);
idx_type = 0;
thisvid.audio_chunks = nai;
thisvid.idx=0;
thisvid.audio_bytes = tot;
/*
* reposition the file
*
*/
InputMediaClose();
int fsize=InputMediaOpen(thisvid.m_lpFilename,0,0,2000000,CacheSize);
if (!fsize) return 0;
//int time=(((double)thisvid.video_frames)/((double)thisvid.fps));
//int abytes=(int)(time*32000)/8;
//thisvid.threshhold=((double)((fsize-abytes)/time)/thisvid.fps)*(4);
//Sleep(1000);
InputMediaSeek(thisvid.movi_start,
INPUT_SEEK_SET);
thisvid.video_pos = 0;
return 1;
}
/*
* Reading Functions
*
*/
/*
* Tries to open an AVI
* with and without an index
*/
int AVIDecaps_Open(char* lpFilename, int Cache, int CacheSize,videoinfo** vidinfo)
{
int ret=0;
strcpy(thisvid.m_lpFilename,lpFilename);
thisvid.m_type=Cache;
::CacheSize=CacheSize;
if (!InputMediaOpen(lpFilename, 0, 0,-1,1000000))
{
return 0;
}
//thisvid.hIOMutex = CreateMutex (NULL, false, NULL);
thisvid.video_pos = 0;
thisvid.audio_posc = 0;
thisvid.audio_posb = 0;
thisvid.idx = NULL;
thisvid.video_index = NULL;
thisvid.audio_index = NULL;
if(AVIDecaps_IsAVI()) {
if(AVIDecaps_FillHeader(1)) {
ret= 1;
}
}
*vidinfo=&::thisvid;
return ret;
}
/*
* Reads the next video Frame into
* buffer, return the actual size of
* the frame.
*
*/
int AVIDecaps_NextVideoFrame(char *buffer, int drop)
{
unsigned int n;
// printf("this=%d\r\n",thisvid.video_pos);
n = thisvid.video_index[thisvid.video_pos].len;
// WaitForSingleObject(thisvid.hIOMutex, INFINITE);
InputMediaSeek(thisvid.video_index[thisvid.video_pos].pos, INPUT_SEEK_SET);
InputMediaRead(buffer, n);
//ReleaseMutex(thisvid.hIOMutex);
thisvid.video_pos++;
// printf("next=%d\r\n",thisvid.video_pos);
return n;
}
/*
* Reads any amount of audio
* data. FIXME : should return
* the actual number read.
*/
int AVIDecaps_ReadAudio(char *audbuf, int bytes)
{
int nr, left = 0, todo;
int tempb=bytes;
nr = 0;
/*
* We loop until we parsed enough
* chunks for the amount we want
*
*/
while(bytes > 0)
{
left = thisvid.audio_index[thisvid.audio_posc].len - thisvid.audio_posb;
if(!left)
{
if(thisvid.audio_posc>=thisvid.audio_chunks-1)
{
//ReleaseMutex(thisvid.hIOMutex);
return nr;
}
thisvid.audio_posc++;
thisvid.audio_posb = 0;
continue;
}
if(bytes<left)
todo = bytes;
else
todo = left;
//WaitForSingleObject(thisvid.hIOMutex, INFINITE);
InputMediaSeek(thisvid.audio_index[thisvid.audio_posc].pos + thisvid.audio_posb, INPUT_SEEK_SET);
InputMediaRead(audbuf + nr, todo);
// ReleaseMutex(thisvid.hIOMutex);
bytes -= todo;
nr += todo;
thisvid.audio_posb += todo;
}
if (!nr) printf("read failed pos=%d bytes=%d\r\n",InputMediaSeek(0,INPUT_SEEK_CUR),tempb);
return nr;
}
double AVIDecaps_FrameRate()
{
return (double) thisvid.fps;
}
int AVIDecaps_AudioSeek(long bytes)
{
long n0, n1, n;
if(!thisvid.audio_index) {
return -1;
}
if(bytes < 0)
bytes = 0;
n0 = 0;
n1 = thisvid.audio_chunks;
while(n0 < n1 - 1)
{
n = (n0 + n1) / 2;
if(thisvid.audio_index[n].tot > bytes)
n1 = n;
else
n0 = n;
}
thisvid.audio_posc = n0;
if(thisvid.audio_index[n0].len > 1000) {
thisvid.audio_posb = bytes - thisvid.audio_index[n0].tot;
}
else {
thisvid.audio_posb = 0;
}
return 0;
}
int AVIDecaps_isKeyframe(long frame)
{
return thisvid.video_index[frame].flags; // & AVIIF_KEYFRAME;
}
int AVIDecaps_Seek(int percent)
{
long frame;
double ratio;
long audio_bytes;
//WaitForSingleObject(thisvid.hIOMutex, INFINITE);
/*
* compute the desired
* frame number
*
*/
frame = (long) (percent * thisvid.video_frames / 100);
/*
* and go to the next
* keyframe.
*
*/
while(!AVIDecaps_isKeyframe(frame)) {
frame++;
}
/*
* now set video
* position.
*
*/
//AVIDecaps_VideoSeek(frame);
thisvid.video_pos = frame;
/*
* calculate what ratio
* it corresponds to
*
*/
if(thisvid.audio_strn > 0) {
ratio = (double) ((double) frame / (double) thisvid.video_frames);
/*
* and set audio
* position
*
*/
audio_bytes = (long) (ratio * thisvid.audio_bytes);
audio_bytes += audio_bytes % 4;
AVIDecaps_AudioSeek(audio_bytes);
//ReleaseMutex(thisvid.hIOMutex);
return thisvid.audio_bytes-audio_bytes;
}
return 1;
}
int AVIDecaps_ReSeekAudio()
{
double ratio;
long audio_bytes;
if(thisvid.audio_strn > 0) {
//WaitForSingleObject(thisvid.hIOMutex, INFINITE);
ratio = (double) ((double) thisvid.video_pos / (double) thisvid.video_frames);
audio_bytes = (long) (ratio * thisvid.audio_bytes);
audio_bytes += audio_bytes % 4;
AVIDecaps_AudioSeek(audio_bytes);
//ReleaseMutex(thisvid.hIOMutex);
}
return thisvid.audio_bytes-audio_bytes;
}
double AVIDecaps_GetProgress()
{
return (double) ((double)(thisvid.video_pos))*100.0/((double)thisvid.video_frames);
}
int AVIDecaps_Close()
{
printf("Close\r\n");
InputMediaClose();
if (thisvid.video_index) realloc(thisvid.video_index,0);
//printf("index2\r\n");
if (thisvid.audio_index) realloc(thisvid.audio_index,0);
//printf("index3\r\n");
if (thisvid.idx) free(thisvid.idx);
thisvid.video_index=0;
thisvid.audio_index=0;
thisvid.idx=0;
printf("Closed reader\r\n");
return 1;
}
void InitializeReaderAVI(reader* rd)
{
rd->READER_Open=AVIDecaps_Open;
rd->READER_ReadAudio=AVIDecaps_ReadAudio;
rd->READER_NextVideoFrame=AVIDecaps_NextVideoFrame;
rd->READER_Seek=AVIDecaps_Seek;
rd->READER_ReSeekAudio=AVIDecaps_ReSeekAudio;
rd->READER_GetProgress=AVIDecaps_GetProgress;
rd->READER_Close=AVIDecaps_Close;
}
#ifdef __cplusplus
extern "C" {
#endif
#include "common.h"
#include "../decore.h"
enum CodecID {
CODEC_ID_MP2,
CODEC_ID_MSMPEG4,
};
enum CodecType {
CODEC_TYPE_VIDEO,
CODEC_TYPE_AUDIO,
};
enum PixelFormat {
PIX_FMT_YUV420P,
PIX_FMT_YUV422,
PIX_FMT_RGB24,
PIX_FMT_BGR24,
};
/* in bytes */
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 18432
/* motion estimation type */
extern int motion_estimation_method;
#define ME_ZERO 0
#define ME_FULL 1
#define ME_LOG 2
#define ME_PHODS 3
/* encoding support */
#define CODEC_FLAG_HQ 0x0001 /* high quality (non real time) encoding */
#define CODEC_FLAG_QSCALE 0x0002 /* use fixed qscale */
#define FRAME_RATE_BASE 10000
typedef struct AVCodecContext {
int bit_rate;
int flags;
/* video only */
int frame_rate; /* frames per sec multiplied by FRAME_RATE_BASE */
int width, height;
int gop_size; /* 0 = intra only */
int pix_fmt; /* pixel format, see PIX_FMT_xxx */
/* audio only */
int sample_rate; /* samples per sec */
int channels;
/* the following data should not be initialized */
int frame_size; /* in samples, initialized when calling 'init' */
int frame_number; /* audio or video frame number */
int key_frame; /* true if the previous compressed frame was
a key frame (intra, or seekable) */
int quality; /* quality of the previous encoded frame
(between 1 (good) and 31 (bad)) */
struct AVCodec *codec;
void *priv_data;
/* the following fields are ignored */
char codec_name[32];
int codec_type; /* see CODEC_TYPE_xxx */
int codec_id; /* see CODEC_ID_xxx */
unsigned int codec_tag; /* codec tag, only used if unknown codec */
} AVCodecContext;
typedef struct AVCodec {
char *name;
int type;
int id;
int priv_data_size;
int (*init)(AVCodecContext *);
int (*encode)(AVCodecContext *, UINT8 *buf, int buf_size, void *data);
int (*close)(AVCodecContext *);
int (*decode)(AVCodecContext *, void *outdata, int *outdata_size,
UINT8 *buf, int buf_size);
struct AVCodec *next;
} AVCodec;
/* three components are given, that's all */
//typedef struct AVPicture {
// UINT8 *data[3];
// int linesize[3];
// unsigned char* rgbbuff;
// UINT8 *last_picture[3];
// int keyframe;
//} AVPicture;
extern AVCodec msmpeg4_decoder;
/* resample.c */
struct ReSampleContext;
typedef struct ReSampleContext ReSampleContext;
ReSampleContext *audio_resample_init(int output_channels, int input_channels,
int output_rate, int input_rate);
int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples);
void audio_resample_close(ReSampleContext *s);
/* YUV420 format is assumed ! */
struct ImgReSampleContext;
typedef struct ImgReSampleContext ImgReSampleContext;
ImgReSampleContext *img_resample_init(int output_width, int output_height,
int input_width, int input_height);
void img_resample(ImgReSampleContext *s,
AVPicture *output, AVPicture *input);
void img_resample_close(ImgReSampleContext *s);
int img_convert_to_yuv420(UINT8 *img_out, UINT8 *img,
int pix_fmt, int width, int height);
/* external high level API */
extern AVCodec *first_avcodec;
void avcodec_init(void);
void register_avcodec(AVCodec *format);
AVCodec *avcodec_find_encoder(enum CodecID id);
AVCodec *avcodec_find_decoder(enum CodecID id);
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc);
int avcodec_open(AVCodecContext *avctx, AVCodec *codec);
int avcodec_decode_audio(AVCodecContext *avctx, INT16 *samples,
int *frame_size_ptr,
UINT8 *buf, int buf_size);
int avcodec_decode_video(AVCodecContext *avctx, AVPicture *picture,
int *got_picture_ptr,
UINT8 *buf, int buf_size, unsigned char* rgbbuff, int show, int rgbstep);
int avcodec_encode_audio(AVCodecContext *avctx, UINT8 *buf, int buf_size,
const short *samples);
int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size,
const AVPicture *pict);
int avcodec_close(AVCodecContext *avctx);
void avcodec_register_all(void);
void register_all();
#ifdef __cplusplus
}
#endif
/*
* Common bit/dsp utils
* Copyright (c) 2000 Gerard Lantau.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "kos.h"
#include "common.h"
#define NDEBUG
int log2(unsigned int v)
{
int n;
n = 0;
if (v & 0xffff0000) {
v >>= 16;
n += 16;
}
if (v & 0xff00) {
v >>= 8;
n += 8;
}
if (v & 0xf0) {
v >>= 4;
n += 4;
}
if (v & 0xc) {
v >>= 2;
n += 2;
}
if (v & 0x2) {
n++;
}
return n;
}
void init_put_bits(PutBitContext *s,
UINT8 *buffer, int buffer_size,
void *opaque,
void (*write_data)(void *, UINT8 *, int))
{
s->buf = buffer;
s->buf_ptr = s->buf;
s->buf_end = s->buf + buffer_size;
s->bit_cnt=0;
s->bit_buf=0;
s->data_out_size = 0;
s->write_data = write_data;
s->opaque = opaque;
}
static void flush_buffer(PutBitContext *s)
{
int size;
if (s->write_data) {
size = s->buf_ptr - s->buf;
if (size > 0)
s->write_data(s->opaque, s->buf, size);
s->buf_ptr = s->buf;
s->data_out_size += size;
}
}
void put_bits(PutBitContext *s, int n, unsigned int value)
{
unsigned int bit_buf;
int bit_cnt;
#ifdef STATS
st_out_bit_counts[st_current_index] += n;
#endif
// printf("put_bits=%d %x\n", n, value);
// assert(n == 32 || value < (1U << n));
bit_buf = s->bit_buf;
bit_cnt = s->bit_cnt;
// printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
/* XXX: optimize */
if (n < (32-bit_cnt)) {
bit_buf |= value << (32 - n - bit_cnt);
bit_cnt+=n;
} else {
bit_buf |= value >> (n + bit_cnt - 32);
*(UINT32 *)s->buf_ptr = htonl(bit_buf);
//printf("bitbuf = %08x\n", bit_buf);
s->buf_ptr+=4;
if (s->buf_ptr >= s->buf_end)
flush_buffer(s);
bit_cnt=bit_cnt + n - 32;
if (bit_cnt == 0) {
bit_buf = 0;
} else {
bit_buf = value << (32 - bit_cnt);
}
}
s->bit_buf = bit_buf;
s->bit_cnt = bit_cnt;
}
/* return the number of bits output */
long get_bit_count(PutBitContext *s)
{
return (s->buf_ptr - s->buf + s->data_out_size) * 8 + (long)s->bit_cnt;
}
void align_put_bits(PutBitContext *s)
{
put_bits(s,(8 - s->bit_cnt) & 7,0);
}
/* pad the end of the output stream with zeros */
void flush_put_bits(PutBitContext *s)
{
while (s->bit_cnt > 0) {
/* XXX: should test end of buffer */
*s->buf_ptr++=s->bit_buf >> 24;
s->bit_buf<<=8;
s->bit_cnt-=8;
}
flush_buffer(s);
s->bit_cnt=0;
s->bit_buf=0;
}
/* bit input functions */
void init_get_bits(GetBitContext *s,
UINT8 *buffer, int buffer_size)
{
s->buf = buffer;
s->buf_ptr = buffer;
s->buf_end = buffer + buffer_size;
s->bit_cnt = 0;
s->bit_buf = 0;
while (s->buf_ptr < s->buf_end &&
s->bit_cnt < 32) {
s->bit_buf |= (*s->buf_ptr++ << (24 - s->bit_cnt));
s->bit_cnt += 8;
}
}
/* n must be >= 1 and <= 32 */
unsigned int get_bits(GetBitContext *s, int n)
{
unsigned int val;
int bit_cnt;
unsigned int bit_buf;
UINT8 *buf_ptr;
#ifdef STATS
st_bit_counts[st_current_index] += n;
#endif
bit_cnt = s->bit_cnt;
bit_buf = s->bit_buf;
bit_cnt -= n;
if (bit_cnt >= 0) {
/* most common case here */
val = bit_buf >> (32 - n);
bit_buf <<= n;
} else {
val = bit_buf >> (32 - n);
buf_ptr = s->buf_ptr;
buf_ptr += 4;
/* handle common case: we can read everything */
if (buf_ptr <= s->buf_end) {
bit_buf = (buf_ptr[-4] << 24) |
(buf_ptr[-3] << 16) |
(buf_ptr[-2] << 8) |
(buf_ptr[-1]);
} else {
buf_ptr -= 4;
bit_buf = 0;
if (buf_ptr < s->buf_end)
bit_buf |= *buf_ptr++ << 24;
if (buf_ptr < s->buf_end)
bit_buf |= *buf_ptr++ << 16;
if (buf_ptr < s->buf_end)
bit_buf |= *buf_ptr++ << 8;
if (buf_ptr < s->buf_end)
bit_buf |= *buf_ptr++;
}
s->buf_ptr = buf_ptr;
val |= bit_buf >> (32 + bit_cnt);
bit_buf <<= - bit_cnt;
bit_cnt += 32;
}
s->bit_buf = bit_buf;
s->bit_cnt = bit_cnt;
return val;
}
void align_get_bits(GetBitContext *s)
{
int n;
n = s->bit_cnt & 7;
if (n > 0) {
get_bits(s, 8 - n);
}
}
/* VLC decoding */
//#define DEBUG_VLC
#define GET_DATA(v, table, i, wrap, size) \
{\
UINT8 *ptr = (UINT8 *)table + i * wrap;\
switch(size) {\
case 1:\
v = *(UINT8 *)ptr;\
break;\
case 2:\
v = *(UINT16 *)ptr;\
break;\
default:\
v = *(UINT32 *)ptr;\
break;\
}\
}
static int alloc_table(VLC *vlc, int size)
{
int index;
index = vlc->table_size;
vlc->table_size += size;
if (vlc->table_size > vlc->table_allocated) {
vlc->table_allocated += (1 << vlc->bits);
vlc->table_bits = realloc(vlc->table_bits,
sizeof(INT8) * vlc->table_allocated);
vlc->table_codes = realloc(vlc->table_codes,
sizeof(INT16) * vlc->table_allocated);
if (!vlc->table_bits ||
!vlc->table_codes)
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,
UINT32 code_prefix, int n_prefix)
{
int i, j, k, n, table_size, table_index, nb, n1, index;
UINT32 code;
INT8 *table_bits;
INT16 *table_codes;
table_size = 1 << table_nb_bits;
table_index = alloc_table(vlc, table_size);
if (table_index < 0)
return -1;
table_bits = &vlc->table_bits[table_index];
table_codes = &vlc->table_codes[table_index];
for(i=0;i<table_size;i++) {
table_bits[i] = 0;
table_codes[i] = -1;
}
/* 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 code matches the prefix, it is in the table */
n -= n_prefix;
if (n > 0 && (code >> n) == 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++) {
table_bits[j] = n;
table_codes[j] = i;
j++;
}
} else {
n -= table_nb_bits;
j = (code >> n) & ((1 << table_nb_bits) - 1);
/* compute table size */
n1 = -table_bits[j];
if (n > n1)
n1 = n;
table_bits[j] = -n1;
}
}
}
/* second pass : fill auxillary tables recursively */
for(i=0;i<table_size;i++) {
n = table_bits[i];
if (n < 0) {
n = -n;
if (n > table_nb_bits) {
n = table_nb_bits;
table_bits[i] = -n;
}
index = build_table(vlc, n, nb_codes,
bits, bits_wrap, bits_size,
codes, codes_wrap, codes_size,
(code_prefix << table_nb_bits) | i,
n_prefix + table_nb_bits);
if (index < 0)
return -1;
/* note: realloc has been done, so reload tables */
table_bits = &vlc->table_bits[table_index];
table_codes = &vlc->table_codes[table_index];
table_codes[i] = index;
}
}
return table_index;
}
/* wrap and size allow to handle most types of storage. */
int init_vlc(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)
{
vlc->bits = nb_bits;
vlc->table_bits = NULL;
vlc->table_codes = NULL;
vlc->table_allocated = 0;
vlc->table_size = 0;
if (build_table(vlc, nb_bits, nb_codes,
bits, bits_wrap, bits_size,
codes, codes_wrap, codes_size,
0, 0) < 0) {
if (vlc->table_bits)
free(vlc->table_bits);
if (vlc->table_codes)
free(vlc->table_codes);
return -1;
}
return 0;
}
void free_vlc(VLC *vlc)
{
free(vlc->table_bits);
free(vlc->table_codes);
}
int get_vlc(GetBitContext *s, VLC *vlc)
{
int bit_cnt, code, n, nb_bits, index;
UINT32 bit_buf;
INT16 *table_codes;
INT8 *table_bits;
UINT8 *buf_ptr;
SAVE_BITS(s);
nb_bits = vlc->bits;
table_codes = vlc->table_codes;
table_bits = vlc->table_bits;
for(;;) {
SHOW_BITS(s, index, nb_bits);
code = table_codes[index];
n = table_bits[index];
if (n > 0) {
/* most common case */
FLUSH_BITS(n);
#ifdef STATS
st_bit_counts[st_current_index] += n;
#endif
break;
} else if (n == 0) {
return -1;
} else {
FLUSH_BITS(nb_bits);
#ifdef STATS
st_bit_counts[st_current_index] += nb_bits;
#endif
nb_bits = -n;
table_codes = vlc->table_codes + code;
table_bits = vlc->table_bits + code;
}
}
RESTORE_BITS(s);
return code;
}
#ifndef COMMON_H
#define COMMON_H
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
//typedef unsigned long UINT64;
typedef signed char INT8;
typedef signed short INT16;
typedef signed int INT32;
//typedef signed long INT64;
typedef short DCTELEM;
/* bit output */
struct PutBitContext;
extern const UINT8 zigzag_direct[64] ;
extern const UINT8 default_intra_matrix[64] ;
extern const UINT8 default_non_intra_matrix[64];
typedef void (*WriteDataFunc)(void *, UINT8 *, int);
typedef struct PutBitContext {
UINT8 *buf, *buf_ptr, *buf_end;
int bit_cnt;
UINT32 bit_buf;
long data_out_size; /* in bytes */
void *opaque;
WriteDataFunc write_data;
} PutBitContext;
void init_put_bits(PutBitContext *s,
UINT8 *buffer, int buffer_size,
void *opaque,
void (*write_data)(void *, UINT8 *, int));
void put_bits(PutBitContext *s, int n, unsigned int value);
long get_bit_count(PutBitContext *s);
void align_put_bits(PutBitContext *s);
void flush_put_bits(PutBitContext *s);
/* jpeg specific put_bits */
void jput_bits(PutBitContext *s, int n, unsigned int value);
void jflush_put_bits(PutBitContext *s);
/* bit input */
typedef struct GetBitContext {
UINT8 *buf, *buf_ptr, *buf_end;
int bit_cnt;
UINT32 bit_buf;
} GetBitContext;
typedef struct VLC {
int bits;
INT16 *table_codes;
INT8 *table_bits;
int table_size, table_allocated;
} VLC;
void init_get_bits(GetBitContext *s,
UINT8 *buffer, int buffer_size);
unsigned int get_bits(GetBitContext *s, int n);
void align_get_bits(GetBitContext *s);
int init_vlc(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);
void free_vlc(VLC *vlc);
int get_vlc(GetBitContext *s, VLC *vlc);
/* macro to go faster */
/* n must be <= 24 */
/* XXX: optimize buffer end test */
#define SHOW_BITS(s, val, n)\
{\
if (bit_cnt < n && buf_ptr < (s)->buf_end) {\
bit_buf |= *buf_ptr++ << (24 - bit_cnt);\
bit_cnt += 8;\
if (bit_cnt < n && buf_ptr < (s)->buf_end) {\
bit_buf |= *buf_ptr++ << (24 - bit_cnt);\
bit_cnt += 8;\
if (bit_cnt < n && buf_ptr < (s)->buf_end) {\
bit_buf |= *buf_ptr++ << (24 - bit_cnt);\
bit_cnt += 8;\
}\
}\
}\
val = bit_buf >> (32 - n);\
}
/* SHOW_BITS with n1 >= n must be been done before */
#define FLUSH_BITS(n)\
{\
bit_buf <<= n;\
bit_cnt -= n;\
}
#define SAVE_BITS(s) \
{\
bit_cnt = (s)->bit_cnt;\
bit_buf = (s)->bit_buf;\
buf_ptr = (s)->buf_ptr;\
}
#define RESTORE_BITS(s) \
{\
(s)->buf_ptr = buf_ptr;\
(s)->bit_buf = bit_buf;\
(s)->bit_cnt = bit_cnt;\
}
/* define it to include statistics code (useful only for optimizing
codec efficiency */
//#define STATS
#ifdef STATS
enum {
ST_UNKNOWN,
ST_DC,
ST_INTRA_AC,
ST_INTER_AC,
ST_INTRA_MB,
ST_INTER_MB,
ST_MV,
ST_NB,
};
extern int st_current_index;
extern unsigned int st_bit_counts[ST_NB];
extern unsigned int st_out_bit_counts[ST_NB];
void print_stats(void);
#endif
/* misc math functions */
/* memory */
void *av_mallocz(int size);
#endif
/*
* DSP utils
* Copyright (c) 2000 Gerard Lantau.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
#ifdef CONFIG_MMX
int mm_flags; /* multimedia extension flags */
#endif
//op_pixels_abs_func pix_abs16x16;
//op_pixels_abs_func pix_abs16x16_x2;
//op_pixels_abs_func pix_abs16x16_y2;
//op_pixels_abs_func pix_abs16x16_xy2;
static UINT8 cropTbl[256 + 2 * MAX_NEG_CROP];
UINT32 squareTbl[512];
void get_pixels(DCTELEM *block, const UINT8 *pixels, int line_size)
{
DCTELEM *p;
const UINT8 *pix;
int i;
/* read the pixels */
p = block;
pix = pixels;
for(i=0;i<8;i++) {
p[0] = pix[0];
p[1] = pix[1];
p[2] = pix[2];
p[3] = pix[3];
p[4] = pix[4];
p[5] = pix[5];
p[6] = pix[6];
p[7] = pix[7];
pix += line_size;
p += 8;
}
}
void put_pixels_clamped(const DCTELEM *block, UINT8 *pixels, int line_size)
{
const DCTELEM *p;
UINT8 *pix;
int i;
UINT8 *cm = cropTbl + MAX_NEG_CROP;
/* read the pixels */
p = block;
pix = pixels;
for(i=0;i<8;i++) {
pix[0] = cm[p[0]];
pix[1] = cm[p[1]];
pix[2] = cm[p[2]];
pix[3] = cm[p[3]];
pix[4] = cm[p[4]];
pix[5] = cm[p[5]];
pix[6] = cm[p[6]];
pix[7] = cm[p[7]];
pix += line_size;
p += 8;
}
}
void add_pixels_clamped(const DCTELEM *block, UINT8 *pixels, int line_size)
{
const DCTELEM *p;
UINT8 *pix;
int i;
UINT8 *cm = cropTbl + MAX_NEG_CROP;
/* read the pixels */
p = block;
pix = pixels;
for(i=0;i<8;i++) {
pix[0] = cm[pix[0] + p[0]];
pix[1] = cm[pix[1] + p[1]];
pix[2] = cm[pix[2] + p[2]];
pix[3] = cm[pix[3] + p[3]];
pix[4] = cm[pix[4] + p[4]];
pix[5] = cm[pix[5] + p[5]];
pix[6] = cm[pix[6] + p[6]];
pix[7] = cm[pix[7] + p[7]];
pix += line_size;
p += 8;
}
}
#define PIXOP(BTYPE, OPNAME, OP, INCR) \
\
static void OPNAME ## _pixels(BTYPE *block, const UINT8 *pixels, int line_size, int h) \
{ \
BTYPE *p; \
const UINT8 *pix; \
\
p = block; \
pix = pixels; \
do { \
OP(p[0], pix[0]); \
OP(p[1], pix[1]); \
OP(p[2], pix[2]); \
OP(p[3], pix[3]); \
OP(p[4], pix[4]); \
OP(p[5], pix[5]); \
OP(p[6], pix[6]); \
OP(p[7], pix[7]); \
pix += line_size; \
p += INCR; \
} while (--h);; \
} \
\
static void OPNAME ## _pixels_x2(BTYPE *block, const UINT8 *pixels, int line_size, int h) \
{ \
BTYPE *p; \
const UINT8 *pix; \
\
p = block; \
pix = pixels; \
do { \
OP(p[0], avg2(pix[0], pix[1])); \
OP(p[1], avg2(pix[1], pix[2])); \
OP(p[2], avg2(pix[2], pix[3])); \
OP(p[3], avg2(pix[3], pix[4])); \
OP(p[4], avg2(pix[4], pix[5])); \
OP(p[5], avg2(pix[5], pix[6])); \
OP(p[6], avg2(pix[6], pix[7])); \
OP(p[7], avg2(pix[7], pix[8])); \
pix += line_size; \
p += INCR; \
} while (--h); \
} \
\
static void OPNAME ## _pixels_y2(BTYPE *block, const UINT8 *pixels, int line_size, int h) \
{ \
BTYPE *p; \
const UINT8 *pix; \
const UINT8 *pix1; \
\
p = block; \
pix = pixels; \
pix1 = pixels + line_size; \
do { \
OP(p[0], avg2(pix[0], pix1[0])); \
OP(p[1], avg2(pix[1], pix1[1])); \
OP(p[2], avg2(pix[2], pix1[2])); \
OP(p[3], avg2(pix[3], pix1[3])); \
OP(p[4], avg2(pix[4], pix1[4])); \
OP(p[5], avg2(pix[5], pix1[5])); \
OP(p[6], avg2(pix[6], pix1[6])); \
OP(p[7], avg2(pix[7], pix1[7])); \
pix += line_size; \
pix1 += line_size; \
p += INCR; \
} while(--h); \
} \
\
static void OPNAME ## _pixels_xy2(BTYPE *block, const UINT8 *pixels, int line_size, int h) \
{ \
BTYPE *p; \
const UINT8 *pix; \
const UINT8 *pix1; \
\
p = block; \
pix = pixels; \
pix1 = pixels + line_size; \
do { \
OP(p[0], avg4(pix[0], pix[1], pix1[0], pix1[1])); \
OP(p[1], avg4(pix[1], pix[2], pix1[1], pix1[2])); \
OP(p[2], avg4(pix[2], pix[3], pix1[2], pix1[3])); \
OP(p[3], avg4(pix[3], pix[4], pix1[3], pix1[4])); \
OP(p[4], avg4(pix[4], pix[5], pix1[4], pix1[5])); \
OP(p[5], avg4(pix[5], pix[6], pix1[5], pix1[6])); \
OP(p[6], avg4(pix[6], pix[7], pix1[6], pix1[7])); \
OP(p[7], avg4(pix[7], pix[8], pix1[7], pix1[8])); \
pix += line_size; \
pix1 += line_size; \
p += INCR; \
} while(--h); \
} \
\
void (*OPNAME ## _pixels_tab[4])(BTYPE *block, const UINT8 *pixels, int line_size, int h) = { \
OPNAME ## _pixels, \
OPNAME ## _pixels_x2, \
OPNAME ## _pixels_y2, \
OPNAME ## _pixels_xy2, \
};
/* rounding primitives */
#define avg2(a,b) ((a+b+1)>>1)
#define avg4(a,b,c,d) ((a+b+c+d+2)>>2)
#define op_put(a, b) a = b
#define op_avg(a, b) a = avg2(a, b)
#define op_sub(a, b) a -= b
PIXOP(UINT8, put, op_put, line_size)
PIXOP(UINT8, avg, op_avg, line_size)
PIXOP(DCTELEM, sub, op_sub, 8)
/* not rounding primitives */
#undef avg2
#undef avg4
#define avg2(a,b) ((a+b)>>1)
#define avg4(a,b,c,d) ((a+b+c+d+1)>>2)
PIXOP(UINT8, put_no_rnd, op_put, line_size)
PIXOP(UINT8, avg_no_rnd, op_avg, line_size)
/* motion estimation */
#undef avg2
#undef avg4
#define avg2(a,b) ((a+b+1)>>1)
#define avg4(a,b,c,d) ((a+b+c+d+2)>>2)
void dsputil_init(void)
{
int i;
for(i=0;i<256;i++) cropTbl[i + MAX_NEG_CROP] = i;
for(i=0;i<MAX_NEG_CROP;i++) {
cropTbl[i] = 0;
cropTbl[i + MAX_NEG_CROP + 256] = 255;
}
for(i=0;i<512;i++) {
squareTbl[i] = (i - 256) * (i - 256);
}
// pix_abs16x16 = pix_abs16x16_c;
// pix_abs16x16_x2 = pix_abs16x16_x2_c;
// pix_abs16x16_y2 = pix_abs16x16_y2_c;
// pix_abs16x16_xy2 = pix_abs16x16_xy2_c;
//av_fdct = jpeg_fdct_ifast;
#ifdef CONFIG_MMX
mm_flags = mm_support();
#if 0
#endif
// if (mm_flags & MM_MMX) {
// pix_abs16x16 = pix_abs16x16_mmx;
// pix_abs16x16_x2 = pix_abs16x16_x2_mmx;
// pix_abs16x16_y2 = pix_abs16x16_y2_mmx;
// pix_abs16x16_xy2 = pix_abs16x16_xy2_mmx;
// av_fdct = fdct_mmx;
// }
// if (mm_flags & MM_MMXEXT) {
pix_abs16x16 = pix_abs16x16_sse;
// }
#endif
}
#ifndef DSPUTIL_H
#define DSPUTIL_H
#include "common.h"
/* dct code */
//typedef short DCTELEM;
void jpeg_fdct_ifast (DCTELEM *data);
void j_rev_dct (DCTELEM *data);
void fdct_mmx(DCTELEM *block);
void (*av_fdct)(DCTELEM *block);
/* pixel operations */
#define MAX_NEG_CROP 384
/* temporary */
extern UINT32 squareTbl[512];
void dsputil_init(void);
void get_pixels(DCTELEM *block, const UINT8 *pixels, int line_size);
void put_pixels_clamped(const DCTELEM *block, UINT8 *pixels, int line_size);
void add_pixels_clamped(const DCTELEM *block, UINT8 *pixels, int line_size);
/* add and put pixel (decoding) */
typedef void (*op_pixels_func)(UINT8 *block, const UINT8 *pixels, int line_size, int h);
extern op_pixels_func put_pixels_tab[4];
extern op_pixels_func avg_pixels_tab[4];
extern op_pixels_func put_no_rnd_pixels_tab[4];
extern op_pixels_func avg_no_rnd_pixels_tab[4];
/* sub pixel (encoding) */
extern void (*sub_pixels_tab[4])(DCTELEM *block, const UINT8 *pixels, int line_size, int h);
#define sub_pixels_2(block, pixels, line_size, dxy) \
sub_pixels_tab[dxy](block, pixels, line_size, 8)
typedef int (*op_pixels_abs_func)(UINT8 *blk1, UINT8 *blk2, int line_size, int h);
op_pixels_abs_func pix_abs16x16;
op_pixels_abs_func pix_abs16x16_x2;
op_pixels_abs_func pix_abs16x16_y2;
op_pixels_abs_func pix_abs16x16_xy2;
/* motion estimation */
int pix_abs16x16_c(UINT8 *blk1, UINT8 *blk2, int lx, int h);
int pix_abs16x16_x2_c(UINT8 *blk1, UINT8 *blk2, int lx, int h);
int pix_abs16x16_y2_c(UINT8 *blk1, UINT8 *blk2, int lx, int h);
int pix_abs16x16_xy2_c(UINT8 *blk1, UINT8 *blk2, int lx, int h);
#ifdef CONFIG_MMX
#define MM_MMX 0x0001
#define MM_MMXEXT 0x0002
#define MM_3DNOW 0x0004
extern int mm_flags;
int mm_support(void);
int pix_abs16x16_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
int pix_abs16x16_sse(UINT8 *blk1, UINT8 *blk2, int lx, int h);
int pix_abs16x16_x2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
int pix_abs16x16_y2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
int pix_abs16x16_xy2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
static inline void emms(void)
{
asm volatile ("emms;");
}
#define __align8 __attribute__ ((aligned (8)))
#else
#define __align8
#endif
#endif
/*
* H263/MPEG4 backend for ffmpeg encoder and decoder
* Copyright (c) 2000,2001 Gerard Lantau.
* H263+ support for custom picture format.
* Copyright (c) 2001 Juan J. Sierralta P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "avcodec.h"
#include "mpegvideo.h"
#include "h263data.h"
#include "mpeg4data.h"
#define NDEBUG
void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n,
int dir)
{
int x, y, wrap, i;
INT16 *ac_val, *ac_val1;
/* find prediction */
if (n < 4) {
x = 2 * s->mb_x + 1 + (n & 1);
y = 2 * s->mb_y + 1 + ((n & 2) >> 1);
wrap = s->mb_width * 2 + 2;
ac_val = s->ac_val[0][0];
} else {
x = s->mb_x + 1;
y = s->mb_y + 1;
wrap = s->mb_width + 2;
ac_val = s->ac_val[n - 4 + 1][0];
}
ac_val += ((y) * wrap + (x)) * 16;
ac_val1 = ac_val;
if (s->ac_pred) {
if (dir == 0) {
/* left prediction */
ac_val -= 16;
for(i=1;i<8;i++) {
block[i*8] += ac_val[i];
}
} else {
/* top prediction */
ac_val -= 16 * wrap;
for(i=1;i<8;i++) {
block[i] += ac_val[i + 8];
}
}
}
/* left copy */
for(i=1;i<8;i++)
ac_val1[i] = block[i * 8];
/* top copy */
for(i=1;i<8;i++)
ac_val1[8 + i] = block[i];
}
static int mid_pred(int a, int b, int c)
{
int vmin, vmax;
vmin = a;
if (b < vmin)
vmin = b;
if (c < vmin)
vmin = c;
vmax = a;
if (b > vmax)
vmax = b;
if (c > vmax)
vmax = c;
return a + b + c - vmin - vmax;
}
INT16 *h263_pred_motion(MpegEncContext * s, int block,
int *px, int *py)
{
int x, y, wrap;
INT16 *A, *B, *C, *mot_val;
x = 2 * s->mb_x + 1 + (block & 1);
y = 2 * s->mb_y + 1 + ((block >> 1) & 1);
wrap = 2 * s->mb_width + 2;
mot_val = s->motion_val[(x) + (y) * wrap];
/* special case for first line */
if (y == 1) {
A = s->motion_val[(x-1) + (y) * wrap];
*px = A[0];
*py = A[1];
} else {
switch(block) {
default:
case 0:
A = s->motion_val[(x-1) + (y) * wrap];
B = s->motion_val[(x) + (y-1) * wrap];
C = s->motion_val[(x+2) + (y-1) * wrap];
break;
case 1:
case 2:
A = s->motion_val[(x-1) + (y) * wrap];
B = s->motion_val[(x) + (y-1) * wrap];
C = s->motion_val[(x+1) + (y-1) * wrap];
break;
case 3:
A = s->motion_val[(x-1) + (y) * wrap];
B = s->motion_val[(x-1) + (y-1) * wrap];
C = s->motion_val[(x) + (y-1) * wrap];
break;
}
*px = mid_pred(A[0], B[0], C[0]);
*py = mid_pred(A[1], B[1], C[1]);
}
return mot_val;
}
/***********************************************/
/* decoding */
static VLC intra_MCBPC_vlc;
static VLC inter_MCBPC_vlc;
static VLC cbpy_vlc;
static VLC mv_vlc;
static VLC dc_lum, dc_chrom;
void init_rl(RLTable *rl)
{
INT8 max_level[MAX_RUN+1], max_run[MAX_LEVEL+1];
UINT8 index_run[MAX_RUN+1];
int last, run, level, start, end, i;
/* compute max_level[], max_run[] and index_run[] */
for(last=0;last<2;last++) {
if (last == 0) {
start = 0;
end = rl->last;
} else {
start = rl->last;
end = rl->n;
}
memset(max_level, 0, MAX_RUN + 1);
memset(max_run, 0, MAX_LEVEL + 1);
memset(index_run, rl->n, MAX_RUN + 1);
for(i=start;i<end;i++) {
run = rl->table_run[i];
level = rl->table_level[i];
if (index_run[run] == rl->n)
index_run[run] = i;
if (level > max_level[run])
max_level[run] = level;
if (run > max_run[level])
max_run[level] = run;
}
rl->max_level[last] = malloc(MAX_RUN + 1);
memcpy(rl->max_level[last], max_level, MAX_RUN + 1);
rl->max_run[last] = malloc(MAX_LEVEL + 1);
memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1);
rl->index_run[last] = malloc(MAX_RUN + 1);
memcpy(rl->index_run[last], index_run, MAX_RUN + 1);
}
}
void init_vlc_rl(RLTable *rl)
{
init_vlc(&rl->vlc, 9, rl->n + 1,
&rl->table_vlc[0][1], 4, 2,
&rl->table_vlc[0][0], 4, 2);
}
/* init vlcs */
/* intra MCBPC, mb_type = (intra), then (intraq) */
static const UINT8 intra_MCBPC_code[8] = { 1, 1, 2, 3, 1, 1, 2, 3 };
static const UINT8 intra_MCBPC_bits[8] = { 1, 3, 3, 3, 4, 6, 6, 6 };
/* inter MCBPC, mb_type = (inter), (intra), (interq), (intraq), (inter4v) */
static const UINT8 inter_MCBPC_code[20] = {
1, 3, 2, 5,
3, 4, 3, 3,
0, 1, 2, 3,
4, 4, 3, 2,
2, 5, 4, 5,
};
static const UINT8 inter_MCBPC_bits[20] = {
1, 4, 4, 6,
5, 8, 8, 7,
12, 12, 12, 12,
6, 9, 9, 9,
3, 7, 7, 8,
};
static const UINT8 cbpy_tab[16][2] =
{
{3,4}, {5,5}, {4,5}, {9,4}, {3,5}, {7,4}, {2,6}, {11,4},
{2,5}, {3,6}, {5,4}, {10,4}, {4,4}, {8,4}, {6,4}, {3,2}
};
static const UINT8 mvtab[33][2] =
{
{1,1}, {1,2}, {1,3}, {1,4}, {3,6}, {5,7}, {4,7}, {3,7},
{11,9}, {10,9}, {9,9}, {17,10}, {16,10}, {15,10}, {14,10}, {13,10},
{12,10}, {11,10}, {10,10}, {9,10}, {8,10}, {7,10}, {6,10}, {5,10},
{4,10}, {7,11}, {6,11}, {5,11}, {4,11}, {3,11}, {2,11}, {3,12},
{2,12}
};
/* third non intra table */
const UINT16 inter_vlc[103][2] = {
{ 0x2, 2 },{ 0xf, 4 },{ 0x15, 6 },{ 0x17, 7 },
{ 0x1f, 8 },{ 0x25, 9 },{ 0x24, 9 },{ 0x21, 10 },
{ 0x20, 10 },{ 0x7, 11 },{ 0x6, 11 },{ 0x20, 11 },
{ 0x6, 3 },{ 0x14, 6 },{ 0x1e, 8 },{ 0xf, 10 },
{ 0x21, 11 },{ 0x50, 12 },{ 0xe, 4 },{ 0x1d, 8 },
{ 0xe, 10 },{ 0x51, 12 },{ 0xd, 5 },{ 0x23, 9 },
{ 0xd, 10 },{ 0xc, 5 },{ 0x22, 9 },{ 0x52, 12 },
{ 0xb, 5 },{ 0xc, 10 },{ 0x53, 12 },{ 0x13, 6 },
{ 0xb, 10 },{ 0x54, 12 },{ 0x12, 6 },{ 0xa, 10 },
{ 0x11, 6 },{ 0x9, 10 },{ 0x10, 6 },{ 0x8, 10 },
{ 0x16, 7 },{ 0x55, 12 },{ 0x15, 7 },{ 0x14, 7 },
{ 0x1c, 8 },{ 0x1b, 8 },{ 0x21, 9 },{ 0x20, 9 },
{ 0x1f, 9 },{ 0x1e, 9 },{ 0x1d, 9 },{ 0x1c, 9 },
{ 0x1b, 9 },{ 0x1a, 9 },{ 0x22, 11 },{ 0x23, 11 },
{ 0x56, 12 },{ 0x57, 12 },{ 0x7, 4 },{ 0x19, 9 },
{ 0x5, 11 },{ 0xf, 6 },{ 0x4, 11 },{ 0xe, 6 },
{ 0xd, 6 },{ 0xc, 6 },{ 0x13, 7 },{ 0x12, 7 },
{ 0x11, 7 },{ 0x10, 7 },{ 0x1a, 8 },{ 0x19, 8 },
{ 0x18, 8 },{ 0x17, 8 },{ 0x16, 8 },{ 0x15, 8 },
{ 0x14, 8 },{ 0x13, 8 },{ 0x18, 9 },{ 0x17, 9 },
{ 0x16, 9 },{ 0x15, 9 },{ 0x14, 9 },{ 0x13, 9 },
{ 0x12, 9 },{ 0x11, 9 },{ 0x7, 10 },{ 0x6, 10 },
{ 0x5, 10 },{ 0x4, 10 },{ 0x24, 11 },{ 0x25, 11 },
{ 0x26, 11 },{ 0x27, 11 },{ 0x58, 12 },{ 0x59, 12 },
{ 0x5a, 12 },{ 0x5b, 12 },{ 0x5c, 12 },{ 0x5d, 12 },
{ 0x5e, 12 },{ 0x5f, 12 },{ 0x3, 7 },
};
const INT8 inter_level[102] = {
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 1, 2, 3, 4,
5, 6, 1, 2, 3, 4, 1, 2,
3, 1, 2, 3, 1, 2, 3, 1,
2, 3, 1, 2, 1, 2, 1, 2,
1, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 2, 3, 1, 2, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1,
};
const INT8 inter_run[102] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 3, 3,
3, 4, 4, 4, 5, 5, 5, 6,
6, 6, 7, 7, 8, 8, 9, 9,
10, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 0, 0, 0, 1, 1, 2,
3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40,
};
static RLTable rl_inter = {
102,
58,
inter_vlc,
inter_run,
inter_level,
};
static const UINT16 h263_format[8][2] = {
{ 0, 0 },
{ 128, 96 },
{ 176, 144 },
{ 352, 288 },
{ 704, 576 },
{ 1408, 1152 },
};
/*
* H263 decoder
* Copyright (c) 2001 Gerard Lantau.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "avcodec.h"
#include "mpegvideo.h"
//#include "msmpeg4data.h"
//#define DEBUG
static int h263_decode_init(AVCodecContext *avctx)
{
MpegEncContext *s = avctx->priv_data;
s->out_format = FMT_H263;
s->width = avctx->width;
s->height = avctx->height;
/* select sub codec */
s->h263_msmpeg4 = 1;
s->h263_pred = 1;
/* for h263, we allocate the images after having read the header */
if (MPV_common_init(s) < 0)
return -1;
msmpeg4_decode_init_vlc(s);
return 0;
}
static int h263_decode_end(AVCodecContext *avctx)
{
MpegEncContext *s = avctx->priv_data;
MPV_common_end(s);
return 0;
}
static int h263_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
UINT8 *buf, int buf_size)
{
MpegEncContext *s = avctx->priv_data;
int ret;
DCTELEM block[6][64];
AVPicture *pict = data;
/* no supplementary picture */
if (buf_size == 0) {
*data_size = 0;
return 0;
}
init_get_bits(&s->gb, buf, buf_size);
ret = msmpeg4_decode_picture_header(s);
if (ret < 0)
return -1;
MPV_frame_start(s);
/* decode each macroblock */
for(s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) {
for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) {
/* DCT & quantize */
msmpeg4_dc_scale(s);
memset(block, 0, sizeof(block));
s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16;
if (msmpeg4_decode_mb(s, block) < 0)
return -1;
MPV_decode_mb(s, block);
}
}
MPV_frame_end(s);
pict->data[0] = s->current_picture[0];
pict->data[1] = s->current_picture[1];
pict->data[2] = s->current_picture[2];
pict->linesize[0] = s->linesize;
pict->linesize[1] = s->linesize / 2;
pict->linesize[2] = s->linesize / 2;
pict->last_picture[0]=s->last_picture[0];
pict->last_picture[1]=s->last_picture[1];
pict->last_picture[2]=s->last_picture[2];
avctx->quality = s->qscale;
*data_size = sizeof(AVPicture);
return buf_size;
}
AVCodec msmpeg4_decoder = {
"msmpeg4",
CODEC_TYPE_VIDEO,
CODEC_ID_MSMPEG4,
sizeof(MpegEncContext),
h263_decode_init,
NULL,
h263_decode_end,
h263_decode_frame,
};
This diff is collapsed.
/*
* Motion estimation
* Copyright (c) 2000,2001 Gerard Lantau.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
static void halfpel_motion_search(MpegEncContext * s,
int *mx_ptr, int *my_ptr, int dmin,
int xmin, int ymin, int xmax, int ymax);
/* config it to test motion vector encoding (send random vectors) */
//#define CONFIG_TEST_MV_ENCODE
static int pix_sum(UINT8 * pix, int line_size)
{
int s, i, j;
s = 0;
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j += 8) {
s += pix[0];
s += pix[1];
s += pix[2];
s += pix[3];
s += pix[4];
s += pix[5];
s += pix[6];
s += pix[7];
pix += 8;
}
pix += line_size - 16;
}
return s;
}
static int pix_norm1(UINT8 * pix, int line_size)
{
int s, i, j;
UINT32 *sq = squareTbl + 256;
s = 0;
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j += 8) {
s += sq[pix[0]];
s += sq[pix[1]];
s += sq[pix[2]];
s += sq[pix[3]];
s += sq[pix[4]];
s += sq[pix[5]];
s += sq[pix[6]];
s += sq[pix[7]];
pix += 8;
}
pix += line_size - 16;
}
return s;
}
static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size)
{
int s, i, j;
UINT32 *sq = squareTbl + 256;
s = 0;
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j += 8) {
s += sq[pix1[0] - pix2[0]];
s += sq[pix1[1] - pix2[1]];
s += sq[pix1[2] - pix2[2]];
s += sq[pix1[3] - pix2[3]];
s += sq[pix1[4] - pix2[4]];
s += sq[pix1[5] - pix2[5]];
s += sq[pix1[6] - pix2[6]];
s += sq[pix1[7] - pix2[7]];
pix1 += 8;
pix2 += 8;
}
pix1 += line_size - 16;
pix2 += line_size - 16;
}
return s;
}
static void no_motion_search(MpegEncContext * s,
int *mx_ptr, int *my_ptr)
{
*mx_ptr = 16 * s->mb_x;
*my_ptr = 16 * s->mb_y;
}
static int full_motion_search(MpegEncContext * s,
int *mx_ptr, int *my_ptr, int range,
int xmin, int ymin, int xmax, int ymax)
{
int x1, y1, x2, y2, xx, yy, x, y;
int mx, my, dmin, d;
UINT8 *pix;
xx = 16 * s->mb_x;
yy = 16 * s->mb_y;
x1 = xx - range + 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
if (x1 < xmin)
x1 = xmin;
x2 = xx + range - 1;
if (x2 > xmax)
x2 = xmax;
y1 = yy - range + 1;
if (y1 < ymin)
y1 = ymin;
y2 = yy + range - 1;
if (y2 > ymax)
y2 = ymax;
pix = s->new_picture[0] + (yy * s->linesize) + xx;
dmin = 0x7fffffff;
mx = 0;
my = 0;
for (y = y1; y <= y2; y++) {
for (x = x1; x <= x2; x++) {
d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x,
s->linesize, 16);
if (d < dmin ||
(d == dmin &&
(abs(x - xx) + abs(y - yy)) <
(abs(mx - xx) + abs(my - yy)))) {
dmin = d;
mx = x;
my = y;
}
}
}
*mx_ptr = mx;
*my_ptr = my;
return dmin;
}
static int log_motion_search(MpegEncContext * s,
int *mx_ptr, int *my_ptr, int range,
int xmin, int ymin, int xmax, int ymax)
{
int x1, y1, x2, y2, xx, yy, x, y;
int mx, my, dmin, d;
UINT8 *pix;
xx = s->mb_x << 4;
yy = s->mb_y << 4;
/* Left limit */
x1 = xx - range;
if (x1 < xmin)
x1 = xmin;
/* Right limit */
x2 = xx + range;
if (x2 > xmax)
x2 = xmax;
/* Upper limit */
y1 = yy - range;
if (y1 < ymin)
y1 = ymin;
/* Lower limit */
y2 = yy + range;
if (y2 > ymax)
y2 = ymax;
pix = s->new_picture[0] + (yy * s->linesize) + xx;
dmin = 0x7fffffff;
mx = 0;
my = 0;
do {
for (y = y1; y <= y2; y += range) {
for (x = x1; x <= x2; x += range) {
d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
dmin = d;
mx = x;
my = y;
}
}
}
range = range >> 1;
x1 = mx - range;
if (x1 < xmin)
x1 = xmin;
x2 = mx + range;
if (x2 > xmax)
x2 = xmax;
y1 = my - range;
if (y1 < ymin)
y1 = ymin;
y2 = my + range;
if (y2 > ymax)
y2 = ymax;
} while (range >= 1);
*mx_ptr = mx;
*my_ptr = my;
return dmin;
}
static int phods_motion_search(MpegEncContext * s,
int *mx_ptr, int *my_ptr, int range,
int xmin, int ymin, int xmax, int ymax)
{
int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
int mx, my, dminx, dminy;
UINT8 *pix;
xx = s->mb_x << 4;
yy = s->mb_y << 4;
/* Left limit */
x1 = xx - range;
if (x1 < xmin)
x1 = xmin;
/* Right limit */
x2 = xx + range;
if (x2 > xmax)
x2 = xmax;
/* Upper limit */
y1 = yy - range;
if (y1 < ymin)
y1 = ymin;
/* Lower limit */
y2 = yy + range;
if (y2 > ymax)
y2 = ymax;
pix = s->new_picture[0] + (yy * s->linesize) + xx;
mx = 0;
my = 0;
x = xx;
y = yy;
do {
dminx = 0x7fffffff;
dminy = 0x7fffffff;
lastx = x;
for (x = x1; x <= x2; x += range) {
d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
dminx = d;
mx = x;
}
}
x = lastx;
for (y = y1; y <= y2; y += range) {
d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
dminy = d;
my = y;
}
}
range = range >> 1;
x = mx;
y = my;
x1 = mx - range;
if (x1 < xmin)
x1 = xmin;
x2 = mx + range;
if (x2 > xmax)
x2 = xmax;
y1 = my - range;
if (y1 < ymin)
y1 = ymin;
y2 = my + range;
if (y2 > ymax)
y2 = ymax;
} while (range >= 1);
/* half pixel search */
*mx_ptr = mx;
*my_ptr = my;
return dminy;
}
/* The idea would be to make half pel ME after Inter/Intra decision to
save time. */
static void halfpel_motion_search(MpegEncContext * s,
int *mx_ptr, int *my_ptr, int dmin,
int xmin, int ymin, int xmax, int ymax)
{
int mx, my, mx1, my1, d, xx, yy, dminh;
UINT8 *pix;
mx = *mx_ptr << 1;
my = *my_ptr << 1;
xx = 16 * s->mb_x;
yy = 16 * s->mb_y;
dminh = dmin;
/* Half pixel search */
mx1 = mx;
my1 = my;
pix = s->new_picture[0] + (yy * s->linesize) + xx;
if ((mx > (xmin << 1)) && mx < (xmax << 1) &&
(my > (ymin << 1)) && my < (ymax << 1)) {
int dx, dy, px, py;
UINT8 *ptr;
for (dy = -1; dy <= 1; dy++) {
for (dx = -1; dx <= 1; dx++) {
if (dx != 0 || dy != 0) {
px = mx1 + dx;
py = my1 + dy;
ptr = s->last_picture[0] + ((py >> 1) * s->linesize) + (px >> 1);
switch (((py & 1) << 1) | (px & 1)) {
default:
case 0:
d = pix_abs16x16(pix, ptr, s->linesize, 16);
break;
case 1:
d = pix_abs16x16_x2(pix, ptr, s->linesize, 16);
break;
case 2:
d = pix_abs16x16_y2(pix, ptr, s->linesize, 16);
break;
case 3:
d = pix_abs16x16_xy2(pix, ptr, s->linesize, 16);
break;
}
if (d < dminh) {
dminh = d;
mx = px;
my = py;
}
}
}
}
}
*mx_ptr = mx - (xx << 1);
*my_ptr = my - (yy << 1);
//fprintf(stderr,"half - MX: %d\tMY: %d\n",*mx_ptr ,*my_ptr);
}
#ifndef CONFIG_TEST_MV_ENCODE
int estimate_motion(MpegEncContext * s,
int mb_x, int mb_y,
int *mx_ptr, int *my_ptr)
{
UINT8 *pix, *ppix;
int sum, varc, vard, mx, my, range, dmin, xx, yy;
int xmin, ymin, xmax, ymax;
range = 8 * (1 << (s->f_code - 1));
/* XXX: temporary kludge to avoid overflow for msmpeg4 */
if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
range = range * 2;
if (s->unrestricted_mv) {
xmin = -16;
ymin = -16;
xmax = s->width;
ymax = s->height;
} else {
xmin = 0;
ymin = 0;
xmax = s->width - 16;
ymax = s->height - 16;
}
switch(s->full_search) {
case ME_ZERO:
default:
no_motion_search(s, &mx, &my);
dmin = 0;
break;
case ME_FULL:
dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax);
break;
case ME_LOG:
dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
break;
case ME_PHODS:
dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
break;
}
// emms();
/* intra / predictive decision */
xx = mb_x * 16;
yy = mb_y * 16;
pix = s->new_picture[0] + (yy * s->linesize) + xx;
/* At this point (mx,my) are full-pell and the absolute displacement */
ppix = s->last_picture[0] + (my * s->linesize) + mx;
sum = pix_sum(pix, s->linesize);
varc = pix_norm1(pix, s->linesize);
vard = pix_norm(pix, ppix, s->linesize);
vard = vard >> 8;
sum = sum >> 8;
varc = (varc >> 8) - (sum * sum);
if (vard <= 64 || vard < varc) {
if (s->full_search != ME_ZERO) {
halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax);
} else {
mx -= 16 * s->mb_x;
my -= 16 * s->mb_y;
}
*mx_ptr = mx;
*my_ptr = my;
return 0;
} else {
*mx_ptr = 0;
*my_ptr = 0;
return 1;
}
}
#else
/* test version which generates valid random vectors */
int estimate_motion(MpegEncContext * s,
int mb_x, int mb_y,
int *mx_ptr, int *my_ptr)
{
int xx, yy, x1, y1, x2, y2, range;
if ((random() % 10) >= 5) {
range = 8 * (1 << (s->f_code - 1));
if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
range = range * 2;
xx = 16 * s->mb_x;
yy = 16 * s->mb_y;
x1 = xx - range;
if (x1 < 0)
x1 = 0;
x2 = xx + range - 1;
if (x2 > (s->width - 16))
x2 = s->width - 16;
y1 = yy - range;
if (y1 < 0)
y1 = 0;
y2 = yy + range - 1;
if (y2 > (s->height - 16))
y2 = s->height - 16;
*mx_ptr = (random() % (2 * (x2 - x1 + 1))) + 2 * (x1 - xx);
*my_ptr = (random() % (2 * (y2 - y1 + 1))) + 2 * (y1 - yy);
return 0;
} else {
*mx_ptr = 0;
*my_ptr = 0;
return 1;
}
}
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// decore options
#define DEC_OPT_INIT 0x00008000
#define DEC_OPT_RELEASE 0x00010000
#define DEC_OPT_SETPP 0x00020000 // set postprocessing mode
#define DEC_OPT_SETOUT 0x00040000 // set output mode
// decore return values
#define DEC_OK 0
#define DEC_MEMORY 1
#define DEC_BAD_FORMAT 2
// supported output formats
#define YUV12 1
#define RGB32 2
#define RGB24 3
#define RGB555 4
#define RGB565 5
#define YUV2 6
#define RGB565R 7
#define RGB565Z 8
#define RGB565RZ 9
#define RGB565ZPP 10
/**
*
**/
/*
typedef struct _DEC_PARAM_
{
int x_dim; // x dimension of the frames to be decoded
int y_dim; // y dimension of the frames to be decoded
unsigned long color_depth; // leaved for compatibility (new value must be NULL)
int output_format;
int dither;
} DEC_PARAM;
typedef struct _DEC_FRAME_
{
void *bmp; // the 24-bit decoded bitmap
void *bitstream; // the decoder buffer
long length; // the lenght of the decoder stream
int render_flag;
} DEC_FRAME;
typedef struct _DEC_SET_
{
int postproc_level; // valid interval are [0..100]
} DEC_SET;
*/
/**
*
**/
// the prototype of the decore() - main decore engine entrance
//
int decore_frame_Div3(unsigned char *stream, int length, unsigned char *bmp,int flag, int Extra);
//int decore_dropframe(unsigned char *stream, int length, unsigned char *bmp);
int decore_Div3(
unsigned long handle, // handle - the handle of the calling entity, must be unique
unsigned long dec_opt, // dec_opt - the option for docoding, see below
void *param1, // param1 - the parameter 1 (it's actually meaning depends on dec_opt
void *param2); // param2 - the parameter 2 (it's actually meaning depends on dec_opt
void divxinit(int width, int height);
void divxdecode(unsigned char* inbuf_ptr, int size, unsigned char* rgbbuff, int show, int rgbstep);
void divxdeinit();
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment