From: <ave...@us...> - 2009-12-10 13:23:54
|
Revision: 7444 http://gemrb.svn.sourceforge.net/gemrb/?rev=7444&view=rev Author: avenger_teambg Date: 2009-12-10 13:23:39 +0000 (Thu, 10 Dec 2009) Log Message: ----------- added BIKPlayer code (still broken) Modified Paths: -------------- gemrb/trunk/gemrb/plugins/CMakeLists.txt gemrb/trunk/gemrb/plugins/Makefile.am Added Paths: ----------- gemrb/trunk/gemrb/plugins/BIKPlayer/ gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlay.cpp gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlay.h gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayer.cpp gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayerDesc.cpp gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayerDesc.h gemrb/trunk/gemrb/plugins/BIKPlayer/GetBitContext.cpp gemrb/trunk/gemrb/plugins/BIKPlayer/GetBitContext.h gemrb/trunk/gemrb/plugins/BIKPlayer/Makefile.am gemrb/trunk/gemrb/plugins/BIKPlayer/common.h gemrb/trunk/gemrb/plugins/BIKPlayer/dct.cpp gemrb/trunk/gemrb/plugins/BIKPlayer/dsputil.h gemrb/trunk/gemrb/plugins/BIKPlayer/fft.cpp gemrb/trunk/gemrb/plugins/BIKPlayer/mem.cpp gemrb/trunk/gemrb/plugins/BIKPlayer/rational.cpp gemrb/trunk/gemrb/plugins/BIKPlayer/rational.h gemrb/trunk/gemrb/plugins/BIKPlayer/rdft.cpp Added: gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlay.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlay.cpp (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlay.cpp 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,655 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2009 The GemRB Project + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $Id: BIKPlay.cpp 6168 2009-05-28 22:28:33Z mattinm $ + * + */ + +/* + * code derived from Bink Audio decoder + * Copyright (c) 2007-2009 Peter Ross (pr...@xv...) + * Copyright (c) 2009 Daniel Verkamp (da...@dr...) + * + */ + + +#include <assert.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <cstdio> +#include "../Core/Video.h" +#include "../Core/Audio.h" +#include "../Core/Variables.h" +#include "BIKPlay.h" +#include "../../includes/ie_types.h" +#include "rational.h" + +static Video *video = NULL; +static unsigned char g_palette[768]; +static int g_truecolor; +static ieDword *cbAtFrame = NULL; +static ieDword *strRef = NULL; + +static const int ff_wma_critical_freqs[25] = { + 100, 200, 300, 400, 510, 630, 770, 920, + 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, + 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500, + 24500, +}; + +BIKPlay::BIKPlay(void) +{ + str = NULL; + autoFree = false; + video = core->GetVideoDriver(); + inbuff = NULL; + maxRow = 0; + rowCount = 0; + frameCount = 0; +} + +BIKPlay::~BIKPlay(void) +{ + if (str && autoFree) { + delete( str ); + } + av_freep((void **) &inbuff); +} + +void BIKPlay::av_set_pts_info(AVRational &time_base, unsigned int pts_num, unsigned int pts_den) +{ + //pts_wrap_bits, if needed, is always 64 + if(av_reduce(time_base.num, time_base.den, pts_num, pts_den, INT_MAX)) { + //bla bla, something didn't work + } + + if(!time_base.num || !time_base.den) + time_base.num = time_base.den = 0; +} + +int BIKPlay::ReadHeader(DataStream *str) +{ + str->Seek(0,GEM_STREAM_START); + str->Read( header.signature, BIK_SIGNATURE_LEN ); + str->ReadDword(&header.filesize); + header.filesize += 8; + str->ReadDword(&header.framecount); + + if (header.framecount > 1000000) { + return -1; + } + + str->ReadDword(&header.maxframesize); + if (header.maxframesize > header.filesize) { + return -1; + } + + str->Seek(4,GEM_CURRENT_POS); + + str->ReadDword(&header.width); + str->ReadDword(&header.height); + + ieDword fps_num, fps_den; + + str->ReadDword(&fps_num); + str->ReadDword(&fps_den); + + if (fps_num == 0 || fps_den == 0) { + // av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num, fps_den); + return -1; + } + //also sets pts_wrap_bits to 64 + av_set_pts_info(v_timebase, fps_den, fps_num); + + str->Seek(4,GEM_CURRENT_POS); + str->ReadDword(&header.tracks); + + //we handle only single tracks, is this a problem with multi language iwd2? + if (header.tracks > 1) { + return -1; + } + + if (header.tracks) { + str->Seek(4 * header.tracks,GEM_CURRENT_POS); + //make sure we use one track, if more needed, rewrite this part + assert(header.tracks==1); + + str->ReadWord(&header.samplerate); + //also sets pts_wrap_bits to 64 + //av_set_pts_info(s_timebase, 1, header.samplerate); //unused, we simply use header.samplerate + str->ReadWord(&header.audioflag); + + str->Seek(4 * header.tracks,GEM_CURRENT_POS); + } + + /* build frame index table */ + ieDword pos, next_pos; + int keyframe; + + str->ReadDword(&pos); + keyframe = pos & 1; + pos &= ~1; + + frames.reserve(header.framecount); + for (unsigned int i = 0; i < header.framecount; i++) { + if (i == header.framecount - 1) { + next_pos = header.filesize; + } else { + str->ReadDword(&next_pos); + } + if (next_pos <= pos) { + // av_log(s, AV_LOG_ERROR, "invalid frame index table\n"); + return -1; + } + //offset, size, keyframe + binkframe frame; + + //the order of instructions is important here! + frame.pos=pos; + frame.keyframe=keyframe; + pos = next_pos&~1; + keyframe = next_pos&1; + frame.size=pos-frame.pos; + //sanity hack, we might as well just go belly up and refuse playing + if (frame.size>header.maxframesize) { + frame.size = header.maxframesize; + } + + frames.push_back(frame); + + } + inbuff = (ieByte *) av_malloc(header.maxframesize); + if (!inbuff) { + return -2; + } + + str->Seek(4, GEM_CURRENT_POS); + return 0; +} + +bool BIKPlay::Open(DataStream* stream, bool autoFree) +{ + validVideo = false; + if (stream == NULL) { + return false; + } + if (str && this->autoFree) { + delete( str ); + } + str = stream; + this->autoFree = autoFree; + + str->Read( &header.signature, BIK_SIGNATURE_LEN ); + if (memcmp( header.signature, BIK_SIGNATURE_DATA, 4 ) == 0) { + validVideo = ReadHeader(stream)==0; + return validVideo; + } + return false; +} + +void BIKPlay::CallBackAtFrames(ieDword cnt, ieDword *arg, ieDword *arg2 ) +{ + maxRow = cnt; + frameCount = 0; + rowCount = 0; + cbAtFrame = arg; + strRef = arg2; +} + +int BIKPlay::Play() +{ + if (!validVideo) { + return 0; + } + //Start Movie Playback + frameCount = 0; + int ret = doPlay( ); + + EndAudio(); + av_freep((void **) &inbuff); + return ret; +} + +//this code could be in the movieplayer parent class +void get_current_time(long &sec, long &usec) { +#ifdef _WIN32 + DWORD time; + time = GetTickCount(); + + sec = time / 1000; + usec = (time % 1000) * 1000; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + + sec = tv.tv_sec; + usec = tv.tv_usec; +#endif +} + +void BIKPlay::timer_start() +{ + get_current_time(timer_last_sec, timer_last_usec); +} + +void BIKPlay::timer_wait() +{ + long sec, usec; + get_current_time(sec, usec); + + while (sec > timer_last_sec) { + usec += 1000000; + timer_last_sec++; + } + + //quick hack, we should rather use the rational time base as ffmpeg + frame_wait = v_timebase.num*1000000/v_timebase.den; + while (usec - timer_last_usec > (long)frame_wait) { + usec -= frame_wait; + video_frameskip++; + } + + long to_sleep = frame_wait - (usec - timer_last_usec); +#ifdef _WIN32 + Sleep(to_sleep / 1000); +#else + usleep(to_sleep); +#endif + + timer_start(); +} + +bool BIKPlay::next_frame() +{ + if (timer_last_sec) timer_wait(); + if(frameCount>=header.framecount) { + return false; + } + binkframe frame = frames[frameCount++]; + frame.size = fileRead( frame.pos, inbuff, frame.size); + ieDword audframesize = *(ieDword *) inbuff; + DecodeAudioFrame(inbuff+4, audframesize); + //DecodeVideoFrame(inbuff+audframesize+4, frame.size-audframesize-4); + if (!timer_last_sec) timer_start(); + return true; +} + +int BIKPlay::doPlay() +{ + int done = 0; + + //bink is always truecolor + g_truecolor = 1; + //palette is not really needed + memset( g_palette, 0, 768 ); + + frame_wait = 0; + timer_last_sec = 0; + video_frameskip = 0; + + if (sound_init( core->GetAudioDrv()->CanPlay())) { + //sound couldn't be initialized + return 1; + } + + video->InitMovieScreen(outputwidth,outputheight); + //meeh, signed/unsigned comparison sucks + if (outputwidth<(signed) header.width || outputheight<(signed) header.height) { + //movie dimensions are higher than available screen + return 2; + } + //video_init(w,h); + + while (!done && next_frame()) { + done = video->PollMovieEvents(); + } + + return 0; +} + +unsigned int BIKPlay::fileRead(unsigned int pos, void* buf, unsigned int count) +{ + unsigned numread; + + str->Seek(pos, GEM_STREAM_START); + numread = str->Read( buf, count ); + return ( numread == count ); +} + +void BIKPlay::showFrame(unsigned char* buf, unsigned int bufw, + unsigned int bufh, unsigned int sx, unsigned int sy, unsigned int w, + unsigned int h, unsigned int dstx, unsigned int dsty) +{ + ieDword titleref = 0; + + if (cbAtFrame && strRef) { + frameCount ++; + if ((rowCount<maxRow) && (frameCount >= cbAtFrame[rowCount]) ) { + rowCount++; + } + //draw subtitle here + if (rowCount) { + titleref = strRef[rowCount-1]; + } + } + video->showFrame(buf,bufw,bufh,sx,sy,w,h,dstx,dsty, g_truecolor, g_palette, titleref); +} + +int BIKPlay::setAudioStream() +{ + ieDword volume; + core->GetDictionary()->Lookup( "Volume Movie", volume) ; + int source = core->GetAudioDrv()->SetupNewStream(0, 0, 0, volume, false, false); + return source; +} + +void BIKPlay::freeAudioStream(int stream) +{ + if (stream > -1) + core->GetAudioDrv()->ReleaseStream(stream, true); +} + +void BIKPlay::queueBuffer(int stream, unsigned short bits, int channels, short* memory, int size, int samplerate) +{ + if (stream > -1) + core->GetAudioDrv()->QueueBuffer(stream, bits, channels, memory, size, samplerate); +} + + +/** + * @file libavcodec/binkaudio.c + * + * Technical details here: + * http://wiki.multimedia.cx/index.php?title=Bink_Audio + */ + +int BIKPlay::sound_init(bool need_init) +{ + int sample_rate = header.samplerate; + int sample_rate_half; + unsigned int i; + int frame_len_bits; + int ret; + + if(need_init) { + s_stream = setAudioStream(); + } else { + s_stream = -1; + return 0; + } + + if(s_stream<0) { + return 0; + } + + if(header.audioflag&BINK_AUD_STEREO) { + header.channels=2; + } + + /* determine frame length */ + if (sample_rate < 22050) { + frame_len_bits = 9; + } else if (sample_rate < 44100) { + frame_len_bits = 10; + } else { + frame_len_bits = 11; + } + //audio frame length + s_frame_len = 1 << frame_len_bits; + + if (header.channels > MAX_CHANNELS) { + //av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels); + return -1; + } + + if (header.audioflag&BINK_AUD_USEDCT) { + s_channels = header.channels; + } else { + // audio is already interleaved for the RDFT format variant + sample_rate *= header.channels; + s_frame_len *= header.channels; + s_channels = 1; + if (header.channels == 2) + frame_len_bits++; + } + + s_overlap_len = s_frame_len / 16; + s_block_size = (s_frame_len - s_overlap_len) * s_channels; + sample_rate_half = (sample_rate + 1) / 2; + s_root = (float) (2.0 / sqrt(s_frame_len)); + + /* calculate number of bands */ + for (s_num_bands = 1; s_num_bands < 25; s_num_bands++) { + if (sample_rate_half <= ff_wma_critical_freqs[s_num_bands - 1]) { + break; + } + } + + s_bands = (unsigned int *) av_malloc((s_num_bands + 1) * sizeof(*s_bands)); + if (!s_bands) { + return -2; + } + + /* populate bands data */ + s_bands[0] = 1; + for (i = 1; i < s_num_bands; i++) + s_bands[i] = ff_wma_critical_freqs[i - 1] * (s_frame_len / 2) / sample_rate_half; + s_bands[s_num_bands] = s_frame_len / 2; + + s_first = 1; + + for (i = 0; i < s_channels; i++) + s_coeffs_ptr[i] = s_coeffs + i * s_frame_len; + + if (header.audioflag&BINK_AUD_USEDCT) + ret = ff_dct_init(&s_trans.dct, frame_len_bits, 0); + else + ret = ff_rdft_init(&s_trans.rdft, frame_len_bits, IRIDFT); + + return ret; +} + +int BIKPlay::EndAudio() +{ + freeAudioStream(s_stream); + av_freep((void **) &s_bands); + if (header.audioflag&BINK_AUD_USEDCT) + ff_dct_end(&s_trans.dct); + else + ff_rdft_end(&s_trans.rdft); + return 0; +} + +static const uint8_t rle_length_tab[16] = { + 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64 +}; + +const uint8_t ff_log2_tab[256]={ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +static inline int float_to_int16_one(const float *src){ + register unsigned int tmp = *(const int32_t*)src; + if(tmp & 0xf0000){ + tmp = (0x43c0ffff - tmp)>>31; + // is this faster on some gcc/cpu combinations? +// if(tmp > 0x43c0ffff) tmp = 0xFFFF; +// else tmp = 0; + } + return tmp - 0x8000; +} + +static void ff_float_to_int16_interleave_c(int16_t *dst, const float **src, long len, int channels){ + int i; + if(channels==2){ + for(i=0; i<len; i++){ + dst[2*i] = float_to_int16_one(src[0]+i); + dst[2*i+1] = float_to_int16_one(src[1]+i); + } + return; + } + //one channel + for(i=0; i<len; i++) + dst[i] = float_to_int16_one(src[0]+i); +} + +/** + * Decode Bink Audio block + * @param[out] out Output buffer (must contain s->block_size elements) + */ +void BIKPlay::DecodeBlock(short *out) +{ + unsigned int ch, i, j, k; + float q, quant[25]; + int width, coeff; + + if (header.audioflag&BINK_AUD_USEDCT) { + s_gb.skip_bits(2); + } + + for (ch = 0; ch < s_channels; ch++) { + FFTSample *coeffs = s_coeffs_ptr[ch]; + q = 0.0; + coeffs[0] = s_gb.get_float(); + coeffs[1] = s_gb.get_float(); + + for (i = 0; i < s_num_bands; i++) { + int value = s_gb.get_bits(8); + quant[i] = (float) pow(10.0, FFMIN(value, 95) * 0.066399999); + } + + // find band (k) + for (k = 0; s_bands[k] * 2 < 2; k++) { + q = quant[k]; + } + + // parse coefficients + i = 2; + while (i < s_frame_len) { + if (s_gb.get_bits(1)) { + j = i + rle_length_tab[s_gb.get_bits(4)] * 8; + } else { + j = i + 8; + } + + if (j > s_frame_len) + j = s_frame_len; + + width = s_gb.get_bits(4); + if (width == 0) { + memset(coeffs + i, 0, (j - i) * sizeof(*coeffs)); + i = j; + while (s_bands[k] * 2 < i) + q = quant[k++]; + } else { + while (i < j) { + if (s_bands[k] * 2 == i) + q = quant[k++]; + coeff = s_gb.get_bits(width); + if (coeff) { + if (s_gb.get_bits(1)) + coeffs[i] = -q * coeff; + else + coeffs[i] = q * coeff; + } else { + coeffs[i] = 0.0; + } + i++; + } + } + } + + if (header.audioflag&BINK_AUD_USEDCT) + ff_dct_calc (&s_trans.dct, coeffs); + else + ff_rdft_calc(&s_trans.rdft, coeffs); + + for (i = 0; i < s_frame_len; i++) + coeffs[i] *= s_root; + } + + ff_float_to_int16_interleave_c(out, (const float **)s_coeffs_ptr, s_frame_len, s_channels); + + if (!s_first) { + unsigned int count = s_overlap_len * s_channels; + int shift = av_log2(count); + for (i = 0; i < count; i++) { + out[i] = (s_previous[i] * (count - i) + out[i] * i) >> shift; + } + } + + memcpy(s_previous, out + s_block_size, + s_overlap_len * s_channels * sizeof(*out)); + + s_first = 0; +} + +//audio samples +int BIKPlay::DecodeAudioFrame(void *data, int data_size) +{ + int bits = data_size*8; + s_gb.init_get_bits((uint8_t *) data, bits); + + unsigned int reported_size = s_gb.get_bits_long(32); + ieWordSigned *samples = (ieWordSigned *) calloc(reported_size+s_block_size,1); + if (!samples) { + return -1; + } + + ieWordSigned *outbuf = samples; + ieWordSigned *samples_end = samples+reported_size/sizeof(ieWordSigned); + + //s_block_size is in sample units + while (s_gb.get_bits_count() < bits && outbuf + s_block_size <= samples_end) { + DecodeBlock(outbuf); + outbuf += s_block_size; + s_gb.get_bits_align32(); + } + + unsigned int ret = (unsigned int) ((uint8_t*)outbuf - (uint8_t*)samples); + + //sample format is signed 16 bit integers + queueBuffer(s_stream, 16, s_channels, samples, ret, header.samplerate); + + free(samples); + if(ret<reported_size) { + //abort(); + return ret; + } + return (unsigned int) reported_size; +} + +//video frame +void BIKPlay::segment_video_play() +{ + if (video_frameskip) { + video_frameskip--; + video_skippedframes++; + } else { + unsigned int dest_x = (outputwidth - header.width) >> 1; + unsigned int dest_y = (outputheight - header.height) >> 1; + //TODO: video buffer + showFrame((ieByte *)0, header.width, header.height, 0, 0, header.width, header.height, dest_x, dest_y); + } +} Added: gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlay.h =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlay.h (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlay.h 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,151 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $Id: BIKPlay.h 6012 2009-05-20 19:10:20Z fuzzie $ + * + */ + +#ifndef BIKPLAY_H +#define BIKPLAY_H + +#include "../../includes/win32def.h" +#include "../../includes/globals.h" +#include "../Core/MoviePlayer.h" +#include "../Core/Interface.h" +#include "common.h" +#include "rational.h" +#include "GetBitContext.h" +#include "dsputil.h" + +typedef struct { + char signature[BIK_SIGNATURE_LEN]; + ieDword filesize; + ieDword framecount; + ieDword maxframesize; + //ieDword framecount2; //unused by player + ieDword width; + ieDword height; + ieDword fps; + ieDword divider; + ieDword videoflag; + ieDword tracks; //BinkAudFlags + //optional if tracks == 1 (original had multiple tracks) + ieWord unknown2; + ieWord channels; + ieWord samplerate; + ieWord audioflag; + ieDword unknown4; +} binkheader; + +typedef struct { + int keyframe; + ieDword pos; + ieDword size; +} binkframe; + +class BIKPlay : public MoviePlayer { + +private: + DataStream* str; + bool autoFree; + bool validVideo; + binkheader header; + std::vector<binkframe> frames; + ieByte *inbuff; + + //subtitle and frame counting + ieDword maxRow; + ieDword rowCount; + ieDword frameCount; + + //audio context (consider packing it in a struct) + unsigned int s_frame_len; + unsigned int s_channels; + int s_overlap_len; + int s_block_size; + unsigned int *s_bands; + float s_root; + unsigned int s_num_bands; + int s_first; + bool s_audio; + int s_stream; //openal stream handle + +#pragma pack(push,16) + FFTSample s_coeffs[BINK_BLOCK_MAX_SIZE]; + short s_previous[BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block +#pragma pack(pop) + + float *s_coeffs_ptr[MAX_CHANNELS]; ///< pointers to the coeffs arrays for float_to_int16_interleave + + union { + RDFTContext rdft; + DCTContext dct; + } s_trans; + GetBitContext s_gb; + + //video context (consider packing it in a struct) + AVRational v_timebase; + long timer_last_sec; + long timer_last_usec; + unsigned int frame_wait; + bool video_rendered_frame; + unsigned int video_frameskip; + bool done; + int outputwidth, outputheight; + unsigned int video_skippedframes; + +private: + void timer_start(); + void timer_wait(); + void segment_video_play(); + bool next_frame(); + int doPlay(); + unsigned int fileRead(unsigned int pos, void* buf, unsigned int count); + void showFrame(unsigned char* buf, unsigned int bufw, + unsigned int bufh, unsigned int sx, unsigned int sy, + unsigned int w, unsigned int h, unsigned int dstx, + unsigned int dsty); + //void setPalette(unsigned char* p, unsigned start, unsigned count); + int pollEvents(); + int setAudioStream(); + void freeAudioStream(int stream); + void queueBuffer(int stream, unsigned short bits, + int channels, short* memory, + int size, int samplerate); + int sound_init(bool need_init); + void av_set_pts_info(AVRational &time_base, unsigned int pts_num, unsigned int pts_den); + int ReadHeader(DataStream *str); + void DecodeBlock(short *out); + int DecodeAudioFrame(void *data, int data_size); + int DecodeVideoFrame(void *data, int data_size); + int EndAudio(); + int PlayBik(DataStream *stream); +public: + BIKPlay(void); + ~BIKPlay(void); + bool Open(DataStream* stream, bool autoFree = true); + void CallBackAtFrames(ieDword cnt, ieDword *arg, ieDword *arg2); + int Play(); + +public: + void release(void) + { + delete this; + } +}; + +#endif Added: gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayer.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayer.cpp (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayer.cpp 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,53 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $Id: BIKPlayer.cpp 6005 2009-05-19 10:21:38Z lynxlupodian $ + * + */ + +// BIKPlayer.cpp : Defines the entry point for the DLL application. +// + +#include "../../includes/win32def.h" +#include "BIKPlayerDesc.h" +#include "../../includes/globals.h" + +#ifdef WIN32 +#include <windows.h> + +BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, + LPVOID lpReserved) +{ + return TRUE; +} + +#endif + +GEM_EXPORT_DLL ClassDesc* LibClassDesc() +{ + return &BIKPlayCD; +} + +GEM_EXPORT_DLL const char* LibDescription() +{ + return "BIK Video Player"; +} + +GEM_EXPORT_DLL const char* LibVersion() +{ + return VERSION_GEMRB; +} Added: gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayerDesc.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayerDesc.cpp (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayerDesc.cpp 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,57 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $Id: BIKPlayerDesc.cpp 6005 2009-05-19 10:21:38Z lynxlupodian $ + * + */ + +#include "BIKPlay.h" +#include "BIKPlayerDesc.h" + +BIKPlayerDesc::BIKPlayerDesc(void) +{ +} + +BIKPlayerDesc::~BIKPlayerDesc(void) +{ +} + +void* BIKPlayerDesc::Create(void) +{ + return new BIKPlay(); +} + +const char* BIKPlayerDesc::ClassName(void) +{ + return "BIKPlayer"; +} + +SClass_ID BIKPlayerDesc::SuperClassID(void) +{ + return IE_MVE_CLASS_ID; //same as mve (only one may be active) +} + + +Class_ID BIKPlayerDesc::ClassID(void) +{ + return Class_ID( 0x5a271856, 0xa82648af ); +} + +const char* BIKPlayerDesc::InternalName(void) +{ + return "BIKPlayer"; +} Added: gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayerDesc.h =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayerDesc.h (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/BIKPlayerDesc.h 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,40 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $Id: BIKPlayerDesc.h 6005 2009-05-19 10:21:38Z lynxlupodian $ + * + */ + +#ifndef BIKPLAYERDESC_H +#define BIKPLAYERDESC_H + +#include "../../includes/globals.h" +#include "../Core/ClassDesc.h" + +class BIKPlayerDesc : public ClassDesc { +public: + BIKPlayerDesc(void); + ~BIKPlayerDesc(void); + void* Create(void); + const char* ClassName(void); + SClass_ID SuperClassID(void); + Class_ID ClassID(void); + const char* InternalName(void); +}; +static BIKPlayerDesc BIKPlayCD; + +#endif Added: gemrb/trunk/gemrb/plugins/BIKPlayer/GetBitContext.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/GetBitContext.cpp (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/GetBitContext.cpp 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,76 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2009 The GemRB Project + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $Id: GetBitContext.cpp 6168 2009-05-28 22:28:33Z mattinm $ + * + */ + +// code derived from FFMPEG's libavcodec/get_bits.h +// copyright (c) 2004 Michael Niedermayer <mic...@gm...> +// and binkaudio.cpp +// Copyright (c) 2007-2009 Peter Ross (pr...@xv...) +// Copyright (c) 2009 Daniel Verkamp (da...@dr...) + +#include <math.h> +#include "GetBitContext.h" + +//don't return more than 25 bits this way +unsigned int GetBitContext::get_bits(int n) { + register unsigned int tmp; + + tmp = AV_RL32(buffer+(index>>3))>>(index&7); + index+=n; + return tmp& (0xffffffff>>(32-n)); +} + +float GetBitContext::get_float() +{ + int power = get_bits(5); + float f = ldexpf((float) get_bits_long(23), power - 23); + if (get_bits(1)) + f = -f; + return f; +} + +void GetBitContext::get_bits_align32() +{ + int n = (-get_bits_count()) & 31; + if (n) skip_bits(n); +} + +unsigned int GetBitContext::get_bits_long(int n) +{ + if(n<=17) return get_bits(n); + else { + int ret= get_bits(16); + return ret | (get_bits(n-16) << 16); + } +} + +void GetBitContext::init_get_bits(const uint8_t *b, int bit_size) +{ + int buffer_size = (bit_size+7)>>3; + if(buffer_size < 0 || bit_size < 0) { + buffer_size = bit_size = 0; + buffer = NULL; + } + + buffer = b; + size_in_bits = bit_size; + buffer_end = buffer + buffer_size; + index=0; +} Added: gemrb/trunk/gemrb/plugins/BIKPlayer/GetBitContext.h =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/GetBitContext.h (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/GetBitContext.h 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,47 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2009 The GemRB Project + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $Id: GetBitContext.h 6168 2009-05-28 22:28:33Z mattinm $ + * + */ + +//code derived from FFMPEG + +#include "common.h" + + +#define AV_RL32(x) \ + ((((const uint8_t*)(x))[3] << 24) | \ + (((const uint8_t*)(x))[2] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) + +class GetBitContext +{ +public: + const uint8_t *buffer, *buffer_end; + int index; + int size_in_bits; +public: + float get_float(); + void skip_bits(int x) { index+=x; } + int get_bits_count() { return index; } + void get_bits_align32(); + unsigned int get_bits(int x); + unsigned int get_bits_long(int n); + void init_get_bits(const uint8_t *b, int bit_size); +}; Added: gemrb/trunk/gemrb/plugins/BIKPlayer/Makefile.am =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/Makefile.am (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/Makefile.am 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,16 @@ +plugin_LTLIBRARIES = libBIKPlayer.la +INCLUDES = $(all_includes) +libBIKPlayer_la_LDFLAGS = -module -version-info 0:0:0 @LIBPTHREAD@ +libBIKPlayer_la_METASOURCES = AUTO +libBIKPlayer_la_SOURCES = \ + BIKPlay.cpp \ + BIKPlayer.cpp \ + BIKPlayerDesc.cpp \ + GetBitContext.cpp \ + dct.cpp \ + fft.cpp \ + rdft.cpp \ + rational.cpp \ + mem.cpp + +noinst_HEADERS = BIKPlay.h BIKPlayerDesc.h GetBitContext.h Added: gemrb/trunk/gemrb/plugins/BIKPlayer/common.h =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/common.h (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/common.h 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,204 @@ +#ifndef AVUTIL_COMMON_H +#define AVUTIL_COMMON_H + +#include "../../includes/win32def.h" +#include "../../includes/globals.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define av_const +#define av_cold +#define av_flatten +#define attribute_deprecated +#define av_unused +#define av_uninit(x) x +#define av_always_inline inline + +#define uint8_t unsigned char +#define uint16_t unsigned short +#define uint32_t unsigned int +#define uint64_t __int64 + +#define int8_t signed char +#define int16_t signed short +#define int32_t signed int +#define int64_t signed __int64 + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef NAN +#define NAN (0.0/0.0) +#endif +#ifndef INFINITY +#define INFINITY (1.0/0.0) +#endif + +/* misc math functions */ + + +extern const uint8_t ff_log2_tab[256]; + +static inline av_const int av_log2(unsigned int v) +{ + int n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +static inline av_const int av_log2_16bit(unsigned int v) +{ + int n = 0; + if (v & 0xff00) { + v >>= 8; + n += 8; + } + //n += ff_log2_tab[v]; + + return n; +} + + +/** + * Clips a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ + +static inline av_const int av_clip(int a, int amin, int amax) +{ + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clips a signed integer value into the 0-255 range. + * @param a value to clip + * @return clipped value + */ + +inline unsigned char av_clip_uint8(int a) +{ + if (a&(~255)) return (-a)>>31; + else return a; +} + +/** + * Clips a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +/* +static inline av_const uint16_t av_clip_uint16(int a) +{ + if (a&(~65535)) return (-a)>>31; + else return a; +} +*/ +/** + * Clips a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +/* +static inline av_const int16_t av_clip_int16(int a) +{ + if ((a+32768) & ~65535) return (a>>31) ^ 32767; + else return a; +} +*/ +/** + * Clips a float value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +/* +static inline av_const float av_clipf(float a, float amin, float amax) +{ + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} +*/ +/** Computes ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ + +/* +static inline av_const int av_ceil_log2(int x) +{ + return av_log2((x - 1) << 1); +} +*/ + +int64_t av_const av_gcd(int64_t a, int64_t b); + +#define BIK_SIGNATURE_LEN 4 +#define BIK_SIGNATURE_DATA "BIKi" + +#define MAX_CHANNELS 2 +#define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11) + +enum BinkAudFlags { + BINK_AUD_16BITS = 0x4000, ///< prefer 16-bit output + BINK_AUD_STEREO = 0x2000, + BINK_AUD_USEDCT = 0x1000 +}; + +void *av_malloc(unsigned int size); +void av_freep(void **ptr); + +//#ifdef HAVE_AV_CONFIG_H +//# include "internal.h" +//#endif /* HAVE_AV_CONFIG_H */ + +#endif /* AVUTIL_COMMON_H */ Added: gemrb/trunk/gemrb/plugins/BIKPlayer/dct.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/dct.cpp (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/dct.cpp 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,97 @@ +/* + * (I)DCT Transforms + * Copyright (c) 2009 Peter Ross (pr...@xv...) + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file libavcodec/dct.c + * (Inverse) Discrete Cosine Transforms + */ + +#define _USE_MATH_DEFINES + +#include <math.h> +#include "dsputil.h" + +av_cold int ff_dct_init(DCTContext *s, int nbits, int inverse) +{ + int n = 1 << nbits; + + s->nbits = nbits; + s->inverse = inverse; + + s->data = (struct FFTComplex *) av_malloc(sizeof(FFTComplex) * 2 * n); + if (!s->data) + return -1; + + if (ff_fft_init(&s->fft, nbits+1, inverse) < 0) + return -1; + + return 0; +} + +static void ff_dct_calc_c(DCTContext *s, FFTSample *data) +{ + int n = 1<<s->nbits; + int i; + +#define ROTATE(i,n) (-M_PI*((n)-0.5f)*(i)/(n)) + if (s->inverse) { + for(i=0; i < n; i++) { + s->data[i].re = (float) (2 * data[i] * cos(ROTATE(i,n))); + s->data[i].im = (float) (2 * data[i] * sin(ROTATE(i,n))); + } + s->data[n].re = 0; + s->data[n].im = 0; + for(i=0; i<n-1; i++) { + s->data[n+i+1].re = (float) (-2 * data[n - (i+1)] * cos(ROTATE(n+i+1,n))); + s->data[n+i+1].im = (float) (-2 * data[n - (i+1)] * sin(ROTATE(n+i+1,n))); + } + }else{ + for(i=0; i < n; i++) { + s->data[i].re = data[n - (i+1)]; + s->data[i].im = 0; + s->data[n+i].re = data[i]; + s->data[n+i].im = 0; + } + } + + ff_fft_permute(&s->fft, s->data); + ff_fft_calc(&s->fft, s->data); + + if (s->inverse) { + for(i=0; i < n; i++) + data[i] = s->data[n-(i+1)].re / (2 * n); + }else { + for(i=0; i < n; i++) + data[i] = (float) (s->data[i].re / (2 * cos(ROTATE(i,n)))); + } +#undef ROTATE +} + +void ff_dct_calc(DCTContext *s, FFTSample *data) +{ + ff_dct_calc_c(s, data); +} + +av_cold void ff_dct_end(DCTContext *s) +{ + ff_fft_end(&s->fft); + av_freep((void **) &s->data); +} Added: gemrb/trunk/gemrb/plugins/BIKPlayer/dsputil.h =================================================================== --- gemrb/trunk/gemrb/plugins/BIKPlayer/dsputil.h (rev 0) +++ gemrb/trunk/gemrb/plugins/BIKPlayer/dsputil.h 2009-12-10 13:23:39 UTC (rev 7444) @@ -0,0 +1,751 @@ +/* + * DSP utils + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer <mic...@gm...> + * + * 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 libavcodec/dsputil.h + * DSP utils. + * note, many functions in here may use MMX which trashes the FPU state, it is + * absolutely necessary to call emms_c() between dsp & float/double code + */ + +#ifndef AVCODEC_DSPUTIL_H +#define AVCODEC_DSPUTIL_H + +#include "common.h" + +//#define DEBUG +/* dct code */ +typedef short DCTELEM; +typedef int DWTELEM; +typedef short IDWTELEM; + +void fdct_ifast (DCTELEM *data); +void fdct_ifast248 (DCTELEM *data); +void ff_jpeg_fdct_islow (DCTELEM *data); +void ff_fdct248_islow (DCTELEM *data); + +void j_rev_dct (DCTELEM *data); +void j_rev_dct4 (DCTELEM *data); +void j_rev_dct2 (DCTELEM *data); +void j_rev_dct1 (DCTELEM *data); +void ff_wmv2_idct_c(DCTELEM *data); + +void ff_fdct_mmx(DCTELEM *block); +void ff_fdct_mmx2(DCTELEM *block); +void ff_fdct_sse2(DCTELEM *block); + +void ff_vector_fmul_add_add_c(float *dst, const float *src0, const float *src1, + const float *src2, int src3, int blocksize, int step); +void ff_vector_fmul_window_c(float *dst, const float *src0, const float *src1, + const float *win, float add_bias, int len); +void ff_float_to_int16_c(int16_t *dst, const float *src, long len); +//void ff_float_to_int16_interleave_c(int16_t *dst, const float **src, long len, int channels); + +/* pixel operations */ +#define MAX_NEG_CROP 1024 + +/* temporary */ +extern uint32_t ff_squareTbl[512]; +extern uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP]; + +/* add and put pixel (decoding) */ +// blocksizes for op_pixels_func are 8x4,8x8 16x8 16x16 +//h for op_pixels_func is limited to {width/2, width} but never larger than 16 and never smaller then 4 +typedef void (*op_pixels_func)(uint8_t *block/*align width (8 or 16)*/, const uint8_t *pixels/*align 1*/, int line_size, int h); +typedef void (*tpel_mc_func)(uint8_t *block/*align width (8 or 16)*/, const uint8_t *pixels/*align 1*/, int line_size, int w, int h); +typedef void (*qpel_mc_func)(uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, int stride); +typedef void (*h264_chroma_mc_func)(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int srcStride, int h, int x, int y); +typedef void (*h264_weight_func)(uint8_t *block, int stride, int log2_denom, int weight, int offset); +typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src, int stride, int log2_denom, int weightd, int weights, int offset); + +#define DEF_OLD_QPEL(name)\ +void ff_put_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, int stride);\ +void ff_put_no_rnd_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, int stride);\ +void ff_avg_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, int stride); + +DEF_OLD_QPEL(qpel16_mc11_old_c) +DEF_OLD_QPEL(qpel16_mc31_old_c) +DEF_OLD_QPEL(qpel16_mc12_old_c) +DEF_OLD_QPEL(qpel16_mc32_old_c) +DEF_OLD_QPEL(qpel16_mc13_old_c) +DEF_OLD_QPEL(qpel16_mc33_old_c) +DEF_OLD_QPEL(qpel8_mc11_old_c) +DEF_OLD_QPEL(qpel8_mc31_old_c) +DEF_OLD_QPEL(qpel8_mc12_old_c) +DEF_OLD_QPEL(qpel8_mc32_old_c) +DEF_OLD_QPEL(qpel8_mc13_old_c) +DEF_OLD_QPEL(qpel8_mc33_old_c) + +#define CALL_2X_PIXELS(a, b, n)\ +static void a(uint8_t *block, const uint8_t *pixels, int line_size, int h){\ + b(block , pixels , line_size, h);\ + b(block+n, pixels+n, line_size, h);\ +} + +/* motion estimation */ +// h is limited to {width/2, width, 2*width} but never larger than 16 and never smaller then 2 +// although currently h<4 is not used as functions with width <8 are neither used nor implemented +typedef int (*me_cmp_func)(void /*MpegEncContext*/ *s, uint8_t *blk1/*align width (8 or 16)*/, uint8_t *blk2/*align 1*/, int line_size, int h)/* __attribute__ ((const))*/; + + +// for snow slices +typedef struct slice_buffer_s slice_buffer; + +/** + * Scantable. + */ +typedef struct ScanTable{ + const uint8_t *scantable; + uint8_t permutated[64]; + uint8_t raster_end[64]; +#if ARCH_PPC + /** Used by dct_quantize_altivec to find last-non-zero */ + DECLARE_ALIGNED(16, uint8_t, inverse[64]); +#endif +} ScanTable; + +void ff_init_scantable(uint8_t *, ScanTable *st, const uint8_t *src_scantable); + +void ff_emulated_edge_mc(uint8_t *buf, uint8_t *src, int linesize, + int block_w, int block_h, + int src_x, int src_y, int w, int h); + +/** + * DSPContext. + */ +typedef struct DSPContext { + /* pixel ops : interface with DCT */ + void (*get_pixels)(DCTELEM *block/*align 16*/, const uint8_t *pixels/*align 8*/, int line_size); + void (*diff_pixels)(DCTELEM *block/*align 16*/, const uint8_t *s1/*align 8*/, const uint8_t *s2/*align 8*/, int stride); + void (*put_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); + void (*put_signed_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); + void (*add_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); + void (*add_pixels8)(uint8_t *pixels, DCTELEM *block, int line_size); + void (*add_pixels4)(uint8_t *pixels, DCTELEM *block, int line_size); + int (*sum_abs_dctelem)(DCTELEM *block/*align 16*/); + /** + * translational global motion compensation. + */ + void (*gmc1)(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int srcStride, int h, int x16, int y16, int rounder); + /** + * global motion compensation. + */ + void (*gmc )(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height); + void (*clear_block)(DCTELEM *block/*align 16*/); + void (*clear_blocks)(DCTELEM *blocks/*align 16*/); + int (*pix_sum)(uint8_t * pix, int line_size); + int (*pix_norm1)(uint8_t * pix, int line_size); +// 16x16 8x8 4x4 2x2 16x8 8x4 4x2 8x16 4x8 2x4 + + me_cmp_func sad[6]; /* identical to pix_absAxA except additional void * */ + me_cmp_func sse[6]; + me_cmp_func hadamard8_diff[6]; + me_cmp_func dct_sad[6]; + me_cmp_func quant_psnr[6]; + me_cmp_func bit[6]; + me_cmp_func rd[6]; + me_cmp_func vsad[6]; + me_cmp_func vsse[6]; + me_cmp_func nsse[6]; + me_cmp_func w53[6]; + me_cmp_func w97[6]; + me_cmp_func dct_max[6]; + me_cmp_func dct264_sad[6]; + + me_cmp_func me_pre_cmp[6]; + me_cmp_func me_cmp[6]; + me_cmp_func me_sub_cmp[6]; + me_cmp_func mb_cmp[6]; + me_cmp_func ildct_cmp[6]; //only width 16 used + me_cmp_func frame_skip_cmp[6]; //only width 8 used + + int (*ssd_int8_vs_int16)(const int8_t *pix1, const int16_t *pix2, + int size); + + /** + * Halfpel motion compensation with rounding (a+b+1)>>1. + * this is an array[4][4] of motion compensation functions for 4 + * horizontal blocksizes (8,16) and the 4 halfpel positions<br> + * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] + * @param block destination where the result is stored + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + op_pixels_func put_pixels_tab[4][4]; + + /** + * Halfpel motion compensation with rounding (a+b+1)>>1. + * This is an array[4][4] of motion compensation functions for 4 + * horizontal blocksizes (8,16) and the 4 halfpel positions<br> + * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] + * @param block destination into which the result is averaged (a+b+1)>>1 + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + op_pixels_func avg_pixels_tab[4][4]; + + /** + * Halfpel motion compensation with no rounding (a+b)>>1. + * this is an array[2][4] of motion compensation functions for 2 + * horizontal blocksizes (8,16) and the 4 halfpel positions<br> + * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] + * @param block destination where the result is stored + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + op_pixels_func put_no_rnd_pixels_tab[4][4]; + + /** + * Halfpel motion compensation with no rounding (a+b)>>1. + * this is an array[2][4] of motion compensation functions for 2 + * horizontal blocksizes (8,16) and the 4 halfpel positions<br> + * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] + * @param block destination into which the result is averaged (a+b)>>1 + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + op_pixels_func avg_no_rnd_pixels_tab[4][4]; + + void (*put_no_rnd_pixels_l2[2])(uint8_t *block/*align width (8 or 16)*/, const uint8_t *a/*align 1*/, const uint8_t *b/*align 1*/, int line_size, int h); + + /** + * Thirdpel motion compensation with rounding (a+b+1)>>1. + * this is an array[12] of motion compensation functions for the 9 thirdpe + * positions<br> + * *pixels_tab[ xthirdpel + 4*ythirdpel ] + * @param block destination where the result is stored + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + tpel_mc_func put_tpel_pixels_tab[11]; //FIXME individual func ptr per width? + tpel_mc_func avg_tpel_pixels_tab[11]; //FIXME individual func ptr per width? + + qpel_mc_func put_qpel_pixels_tab[2][16]; + qpel_mc_func avg_qpel_pixels_tab[2][16]; + qpel_mc_func put_no_rnd_qpel_pixels_tab[2][16]; + qpel_mc_func avg_no_rnd_qpel_pixels_tab[2][16]; + qpel_mc_func put_mspel_pixels_tab[8]; + + /* C version: convert floats from the range [384.0,386.0] to ints in [-32768,32767] + * simd versions: convert floats from [-32768.0,32767.0] without rescaling and arrays are 16byte aligned */ + void (*float_to_int16)(int16_t *dst, const float *src, long len); + void (*float_to_int16_interleave)(int16_t *dst, const float **src, long len, int channels); + + /* (I)DCT */ + void (*fdct)(DCTELEM *block/* align 16*/); + void (*fdct248)(DCTELEM *block/* align 16*/); + + /* IDCT really*/ + void (*idct)(DCTELEM *block/* align 16*/); + + /** + * block -> idct -> clip to unsigned 8 bit -> dest. + * (-1392, 0, 0, ...) -> idct -> (-174, -174, ...) -> put -> (0, 0, ...) + * @param line_size size in bytes of a horizontal line of dest + */ + void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); + + /** + * block -> idct -> add dest -> clip to unsigned 8 bit -> dest. + * @param line_size size in bytes of a horizontal line of dest + */ + void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); + + /** + * idct input permutation. + * several optimized IDCTs need a permutated input (relative to the normal order of the reference + * IDCT) + * this permutation must be performed before the idct_put/add, note, normally this can be merged + * with the zigzag/alternate scan<br> + * an example to avoid confusion: + * - (->decode coeffs -> zigzag reorder -> dequant -> reference idct ->...) + * - (x -> referece dct -> reference idct -> x) + * - (x -> referece dct -> simple_mmx_perm = idct_permutation -> simple_idct_mmx -> x) + * - (->decode coeffs -> zigzag reorder -> simple_mmx_perm -> dequant -> simple_idct_mmx ->...) + */ + uint8_t idct_permutation[64]; + int idct_permutation_type; +#define FF_NO_IDCT_PERM 1 +#define FF_LIBMPEG2_IDCT_PERM 2 +#define FF_SIMPLE_IDCT_PERM 3 +#define FF_TRANSPOSE_IDCT_PERM 4 +#define FF_PARTTRANS_IDCT_PERM 5 +#define FF_SSE2_IDCT_PERM 6 + + int (*try_8x8basis)(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale); + void (*add_8x8basis)(int16_t rem[64], int16_t basis[64], int scale); +#define BASIS_SHIFT 16 +#define RECON_SHIFT 6 + + void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, int w); +#define EDGE_WIDTH 16 +} DSPContext; + +void dsputil_static_init(void); + +int ff_check_alignment(void); + +/** + * permute block according to permuatation. + * @param last last non zero element in scantable order + */ +void ff_block_permute(DCTELEM *block, uint8_t *permutation, const uint8_t *scantable, int last); + +void ff_set_cmp(DSPContext* c, me_cmp_func *cmp, int type); + +#define BYTE_VEC32(c) ((c)*0x01010101UL) + +static inline uint32_t rnd_avg32(uint32_t a, uint32_t b) +{ + return (a | b) - (((a ^ b) & ~BYTE_VEC32(0x01)) >> 1); +} + +static inline uint32_t no_rnd_avg32(uint32_t a, uint32_t b) +{ + return (a & b) + (((a ^ b) & ~BYTE_VEC32(0x01)) >> 1); +} +/* +static inline int get_penalty_factor(int lambda, int lambda2, int type){ + switch(type&0xFF){ + default: + case FF_CMP_SAD: + return lambda>>FF_LAMBDA_SHIFT; + case FF_CMP_DCT: + return (3*lambda)>>(FF_LAMBDA_SHIFT+1); + case FF_CMP_W53: + return (4*lambda)>>(FF_LAMBDA_SHIFT); + case FF_CMP_W97: + return (2*lambda)>>(FF_LAMBDA_SHIFT); + case FF_CMP_SATD: + case FF_CMP_DCT264: + return (2*lambda)>>FF_LAMBDA_SHIFT; + case FF_CMP_RD: + case FF_CMP_PSNR: + case FF_CMP_SSE: + case FF_CMP_NSSE: + return lambda2>>FF_LAMBDA_SHIFT; + case FF_CMP_BIT: + return 1; + } +} +*/ +/** + * Empty mmx state. + * this must be called between any dsp function and float/double code. + * for example sin(); dsp->idct_put(); emms_c(); cos() + */ +#define emms_c() + +/* should be defined by architectures supporting + one or more MultiMedia extension */ +int mm_support(void); +extern int mm_flags; + +//void dsputil_init_alpha(DSPContext* c, AVCodecContext *avctx); +//void dsputil_init_arm(DSPContext* c, AVCodecContext *avctx); +//void dsputil_init_bfin(DSPContext* c, AVCodecContext *avctx); +//void dsputil_init_mlib(DSPContext* c, AVCodecContext *avctx); +//void dsputil_init_mmi(DSPContext* c, AVCodecContext *avctx); +//void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx); +//void dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx); +//void dsputil_init_sh4(DSPContext* c, AVCodecContext *avctx); +//void dsputil_init_vis(DSPContext* c, AVCodecContext *avctx); + +#define DECLARE_ALIGNED_16(t, v) DECLARE_ALIGNED(16, t, v) +#define DECLARE_ALIGNED_8(t, v) DECLARE_ALIGNED(8, t, v) + +#if HAVE_MMX + +#undef emms_c + +static inline void emms(void) +{ + __asm__ volatile ("emms;":::"memory"); +} + + +#define emms_c() \ +{\ + if (mm_flags & FF_MM_MMX)\ + emms();\ +} + +#elif ARCH_ARM + +#if HAVE_NEON +# define STRIDE_ALIGN 16 +#endif + +#elif ARCH_PPC + +#define STRIDE_ALIGN 16 + +#elif HAVE_MMI + +#define STRIDE_ALIGN 16 + +#else + +#define mm_flags 0 +#define mm_support() 0 + +#endif + +#ifndef STRIDE_ALIGN +# define STRIDE_ALIGN 8 +#endif + +/* PSNR */ +/* +void get_psnr(uint8_t *orig_image[3], uint8_t *coded_image[3], + int orig_linesize[3], int coded_linesize, + AVCodecContext *avctx); +*/ +/* FFT computation */ + +/* NOTE: soon integer code will be added, so you must use the + FFTSample type */ +typedef float FFTSample; + +struct MDCTContext; + +typedef struct FFTComplex { + FFTSample re, im; +} FFTComplex; + +typedef struct FFTContext { + int nbits; + int inverse; + uint16_t *revtab; + FFTComplex *exptab; + FFTComplex *exptab1; /* only used by SSE code */ + FFTComplex *tmp_buf; + void (*fft_permute)(struct FFTContext *s, FFTComplex *z); + void (*fft_calc)(struct FFTContext *s, FFTComplex *z); + void (*imdct_calc)(struct MDCTContext *s, FFTSample *output, const FFTSample *input); + void (*imdct_half)(struct MDCTContext *s, FFTSample *output, const FFTSample *input); + void (*mdct_calc)(struct MDCTContext *s, FFTSample *output, const FFTSample *input); + int split_radix; + int permutation; +#define FF_MDCT_PERM_NONE 0 +#define FF_MDCT_PERM_INTERLEAVE 1 +} FFTContext; + +extern FFTSample* const ff_cos_tabs[17]; + +#if CONFIG_HARDCODED_TABLES +#define COSTABLE_CONST const +#define SINTABLE_CONST const +#else +#define COSTABLE_CONST +#define SINTABLE_CONST +#endif + +#define COSTABLE(size) COSTABLE_CONST FFTSample ff_cos_##size[size/2] + +#define SINTABLE(size) SINTABLE_CONST FFTSample ff_sin_##size[size/2] + +extern COSTABLE(16); +extern COSTABLE(32); +extern COSTABLE(64); +extern COSTABLE(128); +extern COSTABLE(256); +extern COSTABLE(512); +extern COSTABLE(1024); +extern COSTABLE(2048); +extern COSTABLE(4096); +extern COSTABLE(8192); +extern COSTABLE(16384); +extern COSTABLE(32768); +extern COSTABLE(65536); + +/** + * Initializes the cosine table in ff_cos_tabs[index] + * \param index index in ff_cos_tabs array of the table to initialize + */ +void ff_init_ff_cos_tabs(int index); + +extern SINTABLE(16); +extern SINTABLE(32); +extern SINTABLE(64); +extern SINTABLE(128); +extern SINTABLE(256); +extern SINTABLE(512); +extern SINTABLE(1024); +extern SINTABLE(2048); +extern SINTABLE(4096); +extern SINTABLE(8192); +extern SINTABLE(16384); +extern SINTABLE(32768); +extern SINTABLE(65536); + +/** + * Sets up a complex FFT. + * @param nbits log2 of the length of the input array + * @param inverse if 0 perform the forward transform, if 1 perform the inverse + */ +int ff_fft_init(FFTContext *s, int nbits, int inverse); +void ff_fft_permute_c(FFTContext *s, FFTComplex *z); +void ff_fft_permute_sse(FFTContext *s, FFTComplex *z); +void ff_fft_permute_neon(FFTContext *s, FFTComplex *z); +void ff_fft_calc_c(FFTContext *s, FFTComplex *z); +void ff_fft_calc_sse(FFTContext *s, FFTComplex *z); +void ff_fft_calc_3dn(FFTContext *s, FFTComplex *z); +void ff_fft_calc_3dn2(FFTContext *s, FFTComplex *z); +void ff_fft_calc_altivec(FFTContext *s, FFTComplex *z); +void ff_fft_calc_neon(FFTContext *s, FFTComplex *z); + +/** + * Do the permutation needed BEFORE calling ff_fft_calc(). + */ +static inline void ff_fft_permute(FFTContext *s, FFTComplex *z) +{ + s->fft_permute(s, z); +} +/** + * Do a complex FFT with the parameters defined in ff_fft_init(). The + * input data must be permuted before. No 1.0/sqrt(n) normalization is done. + */ +static inline void ff_fft_calc(FFTContext *s, FFTComplex *z) +{ + s->fft_calc(s, z); +} +void ff_fft_end(FFTContext *s); + +/* MDCT computation */ + +typedef struct MDCTContext { + int n; /* size of MDCT (i.e. number of input data * 2) */ + int nbits; /* n = 2^nbits */ + /* pre/post rotation tables */ + FFTSample *tcos; + FFTSample *tsin; + FFTContext fft; +} MDCTContext; + +static inline void ff_imdct_calc(MDCTContext *s, FFTSample *output, cons... [truncated message content] |