sna scaler

git-svn-id: svn://kolibrios.org@2349 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2012-02-13 22:34:36 +00:00
parent 4a23260a83
commit 84726c7e7b
7 changed files with 1058 additions and 251 deletions

View File

@ -14,32 +14,12 @@ astream_t astream;
static SNDBUF hBuff; static SNDBUF hBuff;
extern uint8_t *decoder_buffer;
extern volatile uint32_t status; extern volatile uint32_t status;
void audio_thread(void *param); extern volatile uint32_t driver_lock;
void spinlock_lock(volatile uint32_t *val)
{
uint32_t tmp;
__asm__ __volatile__ (
"0:\n\t"
"mov %0, %1\n\t"
"testl %1, %1\n\t"
"jz 1f\n\t"
"movl $68, %%eax\n\t"
"movl $1, %%ebx\n\t"
"int $0x40\n\t"
"jmp 0b\n\t"
"1:\n\t"
"incl %1\n\t"
"xchgl %0, %1\n\t"
"testl %1, %1\n\t"
"jnz 0b\n"
: "+m" (*val), "=&r"(tmp)
::"eax","ebx" );
}
static int snd_format; static int snd_format;
int sample_rate; int sample_rate;
@ -50,11 +30,17 @@ int init_audio(int format)
int version =-1; int version =-1;
char *errstr; char *errstr;
mutex_lock(&driver_lock);
if((err = InitSound(&version)) !=0 ) if((err = InitSound(&version)) !=0 )
{ {
mutex_unlock(&driver_lock);
errstr = "Sound service not installed\n\r"; errstr = "Sound service not installed\n\r";
goto exit_whith_error; goto exit_whith_error;
} };
mutex_unlock(&driver_lock);
printf("sound version 0x%x\n", version); printf("sound version 0x%x\n", version);
if( (SOUND_VERSION>(version&0xFFFF)) || if( (SOUND_VERSION>(version&0xFFFF)) ||
@ -66,8 +52,6 @@ int init_audio(int format)
snd_format = format; snd_format = format;
asm volatile ( "xchgw %bx, %bx");
create_thread(audio_thread, 0, 163840); create_thread(audio_thread, 0, 163840);
return 1; return 1;
@ -89,8 +73,51 @@ double get_master_clock()
return tstamp - audio_delta; return tstamp - audio_delta;
}; };
int decode_audio(AVCodecContext *ctx, queue_t *qa)
{
AVPacket pkt;
AVPacket pkt_tmp;
void audio_thread(void *param) uint8_t *audio_data;
int audio_size;
int len;
int data_size=0;
if( astream.count > AVCODEC_MAX_AUDIO_FRAME_SIZE*7)
return 1;
if( get_packet(qa, &pkt) == 0 )
return 0;
// __asm__("int3");
pkt_tmp = pkt;
while(pkt_tmp.size > 0)
{
data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio3(ctx,(int16_t*)decoder_buffer,
&data_size, &pkt_tmp);
if(len >= 0)
{
pkt_tmp.data += len;
pkt_tmp.size -= len;
mutex_lock(&astream.lock);
memcpy(astream.buffer+astream.count, decoder_buffer, data_size);
astream.count += data_size;
mutex_unlock(&astream.lock);
}
else pkt_tmp.size = 0;
}
av_free_packet(&pkt);
return 1;
};
int audio_thread(void *param)
{ {
SND_EVENT evnt; SND_EVENT evnt;
int buffsize; int buffsize;
@ -121,13 +148,13 @@ void audio_thread(void *param)
(status != 0) ) (status != 0) )
yield(); yield();
spinlock_lock(&astream.lock); mutex_lock(&astream.lock);
{ {
SetBuffer(hBuff, astream.buffer, 0, buffsize); SetBuffer(hBuff, astream.buffer, 0, buffsize);
astream.count -= buffsize; astream.count -= buffsize;
if(astream.count) if(astream.count)
memcpy(astream.buffer, astream.buffer+buffsize, astream.count); memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
spinlock_unlock(&astream.lock); mutex_unlock(&astream.lock);
}; };
if((err = PlayBuffer(hBuff, 0)) !=0 ) if((err = PlayBuffer(hBuff, 0)) !=0 )
@ -163,13 +190,13 @@ void audio_thread(void *param)
offset = evnt.offset; offset = evnt.offset;
spinlock_lock(&astream.lock); mutex_lock(&astream.lock);
{ {
SetBuffer(hBuff, astream.buffer, offset, buffsize); SetBuffer(hBuff, astream.buffer, offset, buffsize);
astream.count -= buffsize; astream.count -= buffsize;
if(astream.count) if(astream.count)
memcpy(astream.buffer, astream.buffer+buffsize, astream.count); memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
spinlock_unlock(&astream.lock); mutex_unlock(&astream.lock);
}; };
break; break;
}; };
@ -221,20 +248,23 @@ void audio_thread(void *param)
if((too_late == 1) || (status == 0)) if((too_late == 1) || (status == 0))
continue; continue;
spinlock_lock(&astream.lock); mutex_lock(&astream.lock);
SetBuffer(hBuff, astream.buffer, offset, buffsize); SetBuffer(hBuff, astream.buffer, offset, buffsize);
astream.count -= buffsize; astream.count -= buffsize;
if(astream.count) if(astream.count)
memcpy(astream.buffer, astream.buffer+buffsize, astream.count); memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
spinlock_unlock(&astream.lock); mutex_unlock(&astream.lock);
} }
return; StopBuffer(hBuff);
DestroyBuffer(hBuff);
return 0;
exit_whith_error: exit_whith_error:
printf(errstr); printf(errstr);
return ; return -1;
}; };

View File

@ -9,6 +9,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <ctype.h>
#include "sound.h" #include "sound.h"
#include "fplay.h" #include "fplay.h"
@ -29,9 +31,13 @@ int audioStream;
int have_sound = 0; int have_sound = 0;
uint8_t *decoder_buffer; uint8_t *decoder_buffer;
extern int sample_rate; extern int sample_rate;
char *movie_file;
queue_t q_video;
queue_t q_audio;
int main( int argc, char *argv[]) int main( int argc, char *argv[])
{ {
@ -42,30 +48,29 @@ int main( int argc, char *argv[])
return -1; return -1;
} }
movie_file = argv[1];
/* register all codecs, demux and protocols */ /* register all codecs, demux and protocols */
avcodec_register_all(); avcodec_register_all();
avdevice_register_all(); avdevice_register_all();
av_register_all(); av_register_all();
if( avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) < 0)
// Open video file
if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
{ {
printf("Cannot open file %s\n\r", argv[1]); printf("Cannot open file %s\n\r", argv[1]);
return -1; // Couldn't open file return -1; // Couldn't open file
}; };
// __asm__ __volatile__("int3"); printf("%s\n\r", __FUNCTION__);
// Retrieve stream information // Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0) if(avformat_find_stream_info(pFormatCtx, NULL)<0)
{ {
printf("Cannot find streams\n\r"); printf("Cannot find streams\n\r");
return -1; return -1;
}; };
// __asm__ __volatile__("int3"); // __asm__ __volatile__("int3");
// dump_format(pFormatCtx, 0, argv[1], 0); // dump_format(pFormatCtx, 0, argv[1], 0);
@ -74,14 +79,14 @@ int main( int argc, char *argv[])
audioStream=-1; audioStream=-1;
for(i=0; i < pFormatCtx->nb_streams; i++) for(i=0; i < pFormatCtx->nb_streams; i++)
{ {
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO
&& videoStream < 0) && videoStream < 0)
{ {
videoStream=i; videoStream=i;
video_time_base = pFormatCtx->streams[i]->time_base; video_time_base = pFormatCtx->streams[i]->time_base;
} }
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO && if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
audioStream < 0) audioStream < 0)
{ {
audioStream=i; audioStream=i;
@ -94,22 +99,24 @@ int main( int argc, char *argv[])
return -1; // Didn't find a video stream return -1; // Didn't find a video stream
} }
// __asm__ __volatile__("int3");
// Get a pointer to the codec context for the video stream // Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec; pCodecCtx=pFormatCtx->streams[videoStream]->codec;
aCodecCtx=pFormatCtx->streams[audioStream]->codec; aCodecCtx=pFormatCtx->streams[audioStream]->codec;
// Find the decoder for the video stream // Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id); pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL) { if(pCodec==NULL) {
printf("Unsupported video codec!\n"); printf("Unsupported codec with id %d for input stream %d\n",
pCodecCtx->codec_id, videoStream);
return -1; // Codec not found return -1; // Codec not found
} }
// Open codec
if(avcodec_open(pCodecCtx, pCodec) < 0) if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{ {
printf("Cannot open video codec\n\r"); printf("Error while opening codec for input stream %d\n",
videoStream);
return -1; // Could not open codec return -1; // Could not open codec
}; };
@ -122,7 +129,7 @@ int main( int argc, char *argv[])
if(aCodec) if(aCodec)
{ {
if(avcodec_open(aCodecCtx, aCodec) >= 0 ) if(avcodec_open2(aCodecCtx, aCodec, NULL) >= 0 )
{ {
WAVEHEADER whdr; WAVEHEADER whdr;
int fmt; int fmt;
@ -143,7 +150,7 @@ int main( int argc, char *argv[])
if( init_audio(fmt) ) if( init_audio(fmt) )
{ {
decoder_buffer = (uint8_t*)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE); decoder_buffer = (uint8_t*)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE*2+64);
if( decoder_buffer != NULL ) if( decoder_buffer != NULL )
{ {
astream.lock = 0; astream.lock = 0;
@ -167,20 +174,14 @@ int main( int argc, char *argv[])
if( !init_video(pCodecCtx)) if( !init_video(pCodecCtx))
return 0; return 0;
// Assign appropriate parts of buffer to image planes in pFrameRGB // __asm__ __volatile__("int3");
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
// __asm__ __volatile__("int3");
decoder(); decoder();
status = 0;
// Free the YUV frame // Free the YUV frame
av_free(pFrame); av_free(pFrame);
//__asm__ __volatile__("int3"); //__asm__ __volatile__("int3");
// Close the codec // Close the codec
@ -196,61 +197,59 @@ int main( int argc, char *argv[])
void decoder() void decoder()
{ {
AVPacket packet; int eof = 0;
AVPacket packet;
int ret;
while(av_read_frame(pFormatCtx, &packet) >=0 ) while( status != 0 && !eof)
{ {
if(packet.stream_index==videoStream) int err;
{
decode_video(pCodecCtx, &packet);
}
else if( (packet.stream_index == audioStream) &&
(have_sound != 0) )
{
uint8_t *audio_data;
int audio_size;
int len;
int data_size=0;
audio_data = packet.data; // __asm__ __volatile__("int3");
audio_size = packet.size;
while(audio_size > 0) if(q_video.size+q_audio.size < 16*1024*1024)
{
err = av_read_frame(pFormatCtx, &packet);
if( err < 0)
{ {
data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; eof = 1;
if (err != AVERROR_EOF)
len = avcodec_decode_audio2(aCodecCtx,(int16_t*)decoder_buffer, printf("av_read_frame: error %x\n", err);
&data_size, audio_data, audio_size); continue;
if(len >= 0)
{
audio_data += len;
audio_size -= len;
while((astream.count + data_size) >
AVCODEC_MAX_AUDIO_FRAME_SIZE*8)
{
yield();
}
spinlock_lock(&astream.lock);
memcpy(astream.buffer+astream.count, decoder_buffer, data_size);
astream.count += data_size;
spinlock_unlock(&astream.lock);
}
else audio_size = 0;
} }
} if(packet.stream_index==videoStream)
// Free the packet that was allocated by av_read_frame {
av_free_packet(&packet); put_packet(&q_video, &packet);
}
else if( (packet.stream_index == audioStream) &&
(have_sound != 0) )
{
put_packet(&q_audio, &packet);
}
else
{
av_free_packet(&packet);
};
decode_video(pCodecCtx, &q_video);
decode_audio(aCodecCtx, &q_audio);
continue;
};
decode_video(pCodecCtx, &q_video);
decode_audio(aCodecCtx, &q_audio);
delay(1);
}; };
ret = 1;
while(status != 0 && ret)
{
ret = decode_video(pCodecCtx, &q_video);
ret |= decode_audio(aCodecCtx, &q_audio);
delay(1);
};
delay(50);
status = 0;
printf("status = 0\n");
delay(200);
}; };
__int64 _lseeki64(int fd, __int64 offset, int origin )
{
int off = offset;
return lseek(fd, off, origin);
}

View File

@ -2,6 +2,48 @@
#define BLACK_MAGIC_SOUND #define BLACK_MAGIC_SOUND
#define BLACK_MAGIC_VIDEO #define BLACK_MAGIC_VIDEO
typedef unsigned int color_t;
typedef unsigned int count_t;
typedef struct
{
int left;
int top;
int right;
int bottom;
}rect_t;
typedef struct
{
uint32_t width;
uint32_t height;
uint32_t pitch;
uint32_t handle;
uint8_t *data;
}bitmap_t;
typedef struct render render_t;
struct render
{
uint32_t caps;
uint32_t ctx_width;
uint32_t ctx_height;
uint32_t win_width;
uint32_t win_height;
bitmap_t bitmap[4];
uint32_t ctx_format;
int target;
enum{
EMPTY, INIT }state;
enum{
NORMAL, MINIMIZED, ROLLED
}win_state;
void (*draw)(render_t *render, AVPicture *picture);
};
typedef struct typedef struct
{ {
volatile uint32_t lock; volatile uint32_t lock;
@ -19,20 +61,54 @@ typedef struct
unsigned int unused[2]; unsigned int unused[2];
}SND_EVENT; }SND_EVENT;
typedef struct
{
unsigned handle;
unsigned io_code;
void *input;
int inp_size;
void *output;
int out_size;
}ioctl_t;
typedef struct {
AVPacketList *first_pkt;
AVPacketList *last_pkt;
int size;
int count;
volatile uint32_t lock;
} queue_t;
int put_packet(queue_t *q, AVPacket *pkt);
int get_packet(queue_t *q, AVPacket *pkt);
extern astream_t astream; extern astream_t astream;
extern AVRational video_time_base; extern AVRational video_time_base;
render_t *create_render(uint32_t width, uint32_t height,
uint32_t ctx_format, uint32_t flags);
int init_render(render_t *render, int width, int height);
void render_adjust_size(render_t *render);
int init_audio(int format); int init_audio(int format);
int audio_thread(void *param);
int init_video(AVCodecContext *ctx); int init_video(AVCodecContext *ctx);
int decode_video(AVCodecContext *ctx, AVPacket *pkt); int video_thread(void *param);
int decode_video(AVCodecContext *ctx, queue_t *qv);
int decode_audio(AVCodecContext *ctx, queue_t *qa);
double get_master_clock(); double get_master_clock();
int create_thread(void (*proc)(void *param), void *param, int stack_size); int create_thread(int (*proc)(void *param), void *param, int stack_size);
void spinlock_lock(volatile uint32_t *val); void mutex_lock(volatile uint32_t *val);
static inline void spinlock_unlock(volatile uint32_t *val) static inline void mutex_unlock(volatile uint32_t *val)
{ {
*val = 0; *val = 0;
} }
@ -77,3 +153,59 @@ static inline void delay(uint32_t time)
"int $0x40" "int $0x40"
::"a"(5), "b"(time)); ::"a"(5), "b"(time));
}; };
static inline draw_bitmap(void *bitmap, int x, int y, int w, int h)
{
__asm__ __volatile__(
"int $0x40"
::"a"(7), "b"(bitmap),
"c"((w << 16) | h),
"d"((x << 16) | y));
}
static inline void BeginDraw(void)
{
__asm__ __volatile__(
"int $0x40" ::"a"(12),"b"(1));
};
static inline void EndDraw(void)
{
__asm__ __volatile__(
"int $0x40" ::"a"(12),"b"(2));
};
static inline void DrawWindow(int x, int y, int w, int h, char *name,
color_t workcolor, uint32_t style)
{
__asm__ __volatile__(
"int $0x40"
::"a"(0),
"b"((x << 16) | (w & 0xFFFF)),
"c"((y << 16) | (h & 0xFFFF)),
"d"((style << 24) | (workcolor & 0xFFFFFF)),
"D"(name));
};
static inline void get_proc_info(char *info)
{
__asm__ __volatile__(
"int $0x40"
::"a"(9), "b"(info), "c"(-1)
:"memory");
}
#define HW_BIT_BLIT (1<<0) /* BGRX blitter */
#define HW_TEX_BLIT (1<<1) /* stretch blit */
#define HW_VID_BLIT (1<<2) /* planar and packed video */
uint32_t InitPixlib(uint32_t flags);
int create_bitmap(bitmap_t *bitmap);
int resize_bitmap(bitmap_t *bitmap);
int blit_bitmap(bitmap_t *bitmap, int dst_x, int dst_y,
int w, int h);

View File

@ -0,0 +1,327 @@
#include <stdint.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#include <fcntl.h>
#include "fplay.h"
#define DISPLAY_VERSION 0x0200 /* 2.00 */
#define SRV_GETVERSION 0
#define SRV_GET_CAPS 3
#define SRV_CREATE_SURFACE 10
#define SRV_BLIT_VIDEO 20
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
//void InitPixlib(uint32_t flags);
static uint32_t service;
static uint32_t blit_caps;
typedef struct
{
uint32_t idx;
union
{
uint32_t opt[2];
struct {
uint32_t max_tex_width;
uint32_t max_tex_height;
}cap1;
};
}hwcaps_t;
static uint32_t get_service(char *name)
{
uint32_t retval = 0;
asm volatile ("int $0x40"
:"=a"(retval)
:"a"(68),"b"(16),"c"(name)
:"memory");
return retval;
};
static int call_service(ioctl_t *io)
{
int retval;
asm volatile("int $0x40"
:"=a"(retval)
:"a"(68),"b"(17),"c"(io)
:"memory","cc");
return retval;
};
#define BUFFER_SIZE(n) ((n)*sizeof(uint32_t))
uint32_t InitPixlib(uint32_t caps)
{
uint32_t api_version;
hwcaps_t hwcaps;
ioctl_t io;
// __asm__ __volatile__("int3");
service = get_service("DISPLAY");
if(service == 0)
goto fail;
io.handle = service;
io.io_code = SRV_GETVERSION;
io.input = NULL;
io.inp_size = 0;
io.output = &api_version;
io.out_size = BUFFER_SIZE(1);
if (call_service(&io)!=0)
goto fail;
if( (DISPLAY_VERSION > (api_version & 0xFFFF)) ||
(DISPLAY_VERSION < (api_version >> 16)))
goto fail;
/*
* Let's see what this service can do
*/
hwcaps.idx = 0;
io.handle = service;
io.io_code = SRV_GET_CAPS;
io.input = &hwcaps;
io.inp_size = sizeof(hwcaps);
io.output = NULL;
io.out_size = 0;
if (call_service(&io)!=0)
goto fail;
blit_caps = hwcaps.opt[0];
printf("\nDISPLAY service handle %x\n", service);
if( blit_caps )
printf("service caps %s%s%s\n",
(blit_caps & HW_BIT_BLIT) != 0 ?"HW_BIT_BLIT ":"",
(blit_caps & HW_TEX_BLIT) != 0 ?"HW_TEX_BLIT ":"",
(blit_caps & HW_VID_BLIT) != 0 ?"HW_VID_BLIT ":"");
blit_caps&= caps;
return blit_caps;
fail:
service = 0;
return 0;
};
int create_bitmap(bitmap_t *bitmap)
{
// __asm__ __volatile__("int3");
if( blit_caps & HW_BIT_BLIT )
{
struct __attribute__((packed)) /* SRV_CREATE_SURFACE */
{
uint32_t handle; // ignored
void *data; // ignored
uint32_t width;
uint32_t height;
uint32_t pitch; // ignored
uint32_t max_width;
uint32_t max_height;
uint32_t format; // reserved mbz
}io_10;
ioctl_t io;
int err;
// printf("create bitmap %d x %d\n",
// bitmap->width, bitmap->height);
io_10.width = bitmap->width;
io_10.height = bitmap->height;
io_10.max_width = 0;
io_10.max_height = 0;
io_10.format = 0;
io.handle = service;
io.io_code = SRV_CREATE_SURFACE;
io.input = &io_10;
io.inp_size = BUFFER_SIZE(8);
io.output = NULL;
io.out_size = 0;
err = call_service(&io);
if(err==0)
{
bitmap->handle = io_10.handle;
bitmap->pitch = io_10.pitch;
bitmap->data = io_10.data;
// printf("Create hardware surface %x pitch %d, buffer %x\n",
// bitmap->handle, bitmap->pitch, bitmap->data);
return 0;
};
return err;
};
uint32_t size;
uint32_t pitch;
uint8_t *buffer;
pitch = ALIGN(bitmap->width*4, 16);
size = pitch * bitmap->height;
buffer = (uint8_t*)user_alloc(size);
if( buffer )
{
bitmap->handle = 0;
bitmap->pitch = pitch;
bitmap->data = buffer;
return 0;
};
printf("Cannot alloc frame buffer\n\r");
return -1;
};
struct blit_call
{
int dstx;
int dsty;
int w;
int h;
int srcx;
int srcy;
int srcw;
int srch;
unsigned char *bitmap;
int stride;
};
int blit_bitmap(bitmap_t *bitmap, int dst_x, int dst_y,
int w, int h)
{
if( blit_caps & HW_BIT_BLIT )
{
/*
* Now you will experience the full power of the dark side...
*/
struct __attribute__((packed))
{
uint32_t handle;
int dst_x;
int dst_y;
int src_x;
int src_y;
uint32_t w;
uint32_t h;
}io_20;
ioctl_t io;
int err;
io_20.handle = bitmap->handle;
io_20.dst_x = dst_x;
io_20.dst_y = dst_y;
io_20.src_x = 0;
io_20.src_y = 0;
io_20.w = w;
io_20.h = h;
io.handle = service;
io.io_code = SRV_BLIT_VIDEO;
io.input = &io_20;
io.inp_size = BUFFER_SIZE(7);
io.output = NULL;
io.out_size = 0;
// printf("do blit %x pitch %d\n",bitmap->handle,
// bitmap->pitch);
err = call_service(&io);
if (call_service(&io)==0)
{
//bitmap->data = NULL; Not now, Serge
// printf("blit done\n");
delay(1);
return 0;
};
return err;
};
volatile struct blit_call bc;
bc.dstx = dst_x;
bc.dsty = dst_y;
bc.w = w;
bc.h = h;
bc.srcx = 0;
bc.srcy = 0;
bc.srcw = w;
bc.srch = h;
bc.stride = bitmap->pitch;
bc.bitmap = bitmap->data;
__asm__ __volatile__(
"int $0x40"
::"a"(73),"b"(0),"c"(&bc));
};
static inline void* user_realloc(void *mem, size_t size)
{
void *val;
__asm__ __volatile__(
"int $0x40"
:"=eax"(val)
:"a"(68),"b"(12),"c"(size),"d"(mem)
:"memory");
return val;
}
int resize_bitmap(bitmap_t *bitmap)
{
// __asm__ __volatile__("int3");
if( blit_caps & HW_BIT_BLIT )
{
/* work in progress */
};
uint32_t size;
uint32_t pitch;
uint8_t *buffer;
pitch = ALIGN(bitmap->width*4, 16);
size = pitch * bitmap->height;
buffer = (uint8_t*)user_realloc(bitmap->data, size);
if( buffer )
{
bitmap->handle = 0;
bitmap->pitch = pitch;
bitmap->data = buffer;
return 0;
};
printf("Cannot realloc frame buffer\n\r");
return -1;
};

View File

@ -74,27 +74,9 @@ extern "C"
#define SND_SETTIMEBASE 18 #define SND_SETTIMEBASE 18
#define SND_GETTIMESTAMP 19 #define SND_GETTIMESTAMP 19
#define PLAY_SYNC 0x80000000 #define PLAY_SYNC 0x80000000
typedef struct
{
unsigned int riff_id;
unsigned int riff_size;
unsigned int riff_format;
unsigned int fmt_id;
unsigned int fmt_size;
unsigned short int wFormatTag;
unsigned short int nChannels;
unsigned int nSamplesPerSec;
unsigned int nAvgBytesPerSec;
unsigned short int nBlockAlign;
unsigned short int wBitsPerSample;
unsigned int data_id;
unsigned int data_size;
} WAVEHEADER;
typedef unsigned int SNDBUF; typedef unsigned int SNDBUF;
int _stdcall InitSound(int *version); int _stdcall InitSound(int *version);
@ -127,6 +109,28 @@ int _stdcall SetMasterVol(int vol);
int _stdcall SetTimeBase(SNDBUF hBuff, double base); int _stdcall SetTimeBase(SNDBUF hBuff, double base);
int _stdcall GetTimeStamp(SNDBUF hBuff, double *stamp); int _stdcall GetTimeStamp(SNDBUF hBuff, double *stamp);
int _stdcall GetDevTime(int *stamp);
typedef struct
{
unsigned int riff_id;
unsigned int riff_size;
unsigned int riff_format;
unsigned int fmt_id;
unsigned int fmt_size;
unsigned short int wFormatTag;
unsigned short int nChannels;
unsigned int nSamplesPerSec;
unsigned int nAvgBytesPerSec;
unsigned short int nBlockAlign;
unsigned short int wBitsPerSample;
unsigned int data_id;
unsigned int data_size;
} WAVEHEADER;
unsigned int _stdcall test_wav(WAVEHEADER *hdr); unsigned int _stdcall test_wav(WAVEHEADER *hdr);

View File

@ -0,0 +1,98 @@
#include <stdint.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#include <fcntl.h>
#include "fplay.h"
extern uint32_t hw2d ;
void mutex_lock(volatile uint32_t *val)
{
uint32_t tmp;
__asm__ __volatile__ (
"0:\n\t"
"mov %0, %1\n\t"
"testl %1, %1\n\t"
"jz 1f\n\t"
"movl $68, %%eax\n\t"
"movl $1, %%ebx\n\t"
"int $0x40\n\t"
"jmp 0b\n\t"
"1:\n\t"
"incl %1\n\t"
"xchgl %0, %1\n\t"
"testl %1, %1\n\t"
"jnz 0b\n"
: "+m" (*val), "=&r"(tmp)
::"eax","ebx" );
}
int64_t _lseeki64(int fd, int64_t offset, int origin )
{
int off = offset;
return lseek(fd, off, origin);
}
int put_packet(queue_t *q, AVPacket *pkt)
{
AVPacketList *q_pkt;
/* duplicate the packet */
if (av_dup_packet(pkt) < 0)
return -1;
q_pkt = av_malloc(sizeof(AVPacketList));
if (!q_pkt)
return -1;
q_pkt->pkt = *pkt;
q_pkt->next = NULL;
mutex_lock(&q->lock);
if (!q->last_pkt)
q->first_pkt = q_pkt;
else
q->last_pkt->next = q_pkt;
q->last_pkt = q_pkt;
q->size += q_pkt->pkt.size + sizeof(*q_pkt);
q->count++;
mutex_unlock(&q->lock);
return 0;
}
int get_packet(queue_t *q, AVPacket *pkt)
{
AVPacketList *q_pkt;
int ret = 0;
mutex_lock(&q->lock);
q_pkt = q->first_pkt;
if (q_pkt)
{
q->first_pkt = q_pkt->next;
if (!q->first_pkt)
q->last_pkt = NULL;
q->count--;
q->size -= q_pkt->pkt.size + sizeof(*q_pkt);
*pkt = q_pkt->pkt;
av_free(q_pkt);
ret = 1;
};
mutex_unlock(&q->lock);
return ret;
}

View File

@ -3,44 +3,39 @@
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
#include <libswscale/swscale.h> #include <libswscale/swscale.h>
#include "sound.h"
#include "fplay.h" #include "fplay.h"
void video_thread(void *param);
void draw_bitmap(void *bitmap, int x, int y, int w, int h)
{
__asm__ __volatile__(
"int $0x40"
::"a"(7), "b"(bitmap),
"c"((w << 16) | h),
"d"((x << 16) | y));
}
typedef struct typedef struct
{ {
AVFrame *frame; AVPicture picture;
uint8_t *buffer;
double pts; double pts;
volatile int ready; volatile int ready;
}vframe_t; }vframe_t;
vframe_t frames[8]; vframe_t frames[4];
struct SwsContext *cvt_ctx; struct SwsContext *cvt_ctx = NULL;
int vfx = 0; int vfx = 0;
int dfx = 0; int dfx = 0;
render_t *render;
int width; int width;
int height; int height;
AVRational video_time_base; AVRational video_time_base;
AVFrame *Frame; AVFrame *Frame;
volatile uint32_t driver_lock;
void get_client_rect(rect_t *rc);
int init_video(AVCodecContext *ctx) int init_video(AVCodecContext *ctx)
{ {
uint32_t size;
int i; int i;
width = ctx->width; width = ctx->width;
@ -48,140 +43,111 @@ int init_video(AVCodecContext *ctx)
printf("w = %d h = %d\n\r", width, height); printf("w = %d h = %d\n\r", width, height);
// __asm__ __volatile__("int3");
render = create_render(ctx->width, ctx->height,
ctx->pix_fmt, HW_BIT_BLIT|HW_TEX_BLIT);
if( render == NULL)
{
printf("Cannot create render\n\r");
return 0;
};
Frame = avcodec_alloc_frame(); Frame = avcodec_alloc_frame();
if ( Frame == NULL ) if ( Frame == NULL )
{ {
printf("Cannot alloc video buffer\n\r"); printf("Cannot alloc video frame\n\r");
return 0; return 0;
}; };
cvt_ctx = sws_getContext( for( i=0; i < 4; i++)
ctx->width,
ctx->height,
ctx->pix_fmt,
ctx->width,
ctx->height,
PIX_FMT_BGR24,
SWS_BILINEAR,
NULL, NULL, NULL);
if(cvt_ctx == NULL)
{ {
printf("Cannot initialize the conversion context!\n"); int ret;
return 0;
}
size = avpicture_get_size(PIX_FMT_RGB24, ctx->width, ctx->height); // printf("alloc picture %d %d %x\n",
// ctx->width, ctx->height, ctx->pix_fmt );
for( i=0; i < 8; i++) ret = avpicture_alloc(&frames[i].picture, ctx->pix_fmt,
{
AVFrame *frame;
frame = avcodec_alloc_frame();
if( frame )
{
uint8_t *buffer = (uint8_t*)av_malloc(size);
if( buffer )
{
avpicture_fill((AVPicture *)frame, buffer, PIX_FMT_BGR24,
ctx->width, ctx->height); ctx->width, ctx->height);
if ( ret != 0 )
frames[i].frame = frame; {
frames[i].buffer = buffer; printf("Cannot alloc video buffer\n\r");
frames[i].pts = 0; return 0;
frames[i].ready = 0;
continue;
};
}; };
printf("Cannot alloc frame buffer\n\r");
return 0; frames[i].pts = 0;
frames[i].ready = 0;
}; };
create_thread(video_thread, 0, 163840); create_thread(video_thread, ctx, 1024*1024);
delay(50);
return 1; return 1;
}; };
int frameFinished=0; int frameFinished=0;
static int frame_count;
int decode_video(AVCodecContext *ctx, AVPacket *pkt) int decode_video(AVCodecContext *ctx, queue_t *qv)
{ {
AVPacket pkt;
double pts; double pts;
AVPicture pict;
const uint8_t *data[4];
double av_time; double av_time;
// __asm__("int3"); if(frames[dfx].ready != 0 )
return 1;
if(avcodec_decode_video(ctx, Frame, &frameFinished, if( get_packet(qv, &pkt) == 0 )
pkt->data, pkt->size) <= 0) return 0;
printf("decode error\n");
if( pkt->dts == AV_NOPTS_VALUE && frameFinished = 0;
Frame->reordered_opaque != AV_NOPTS_VALUE)
pts= Frame->reordered_opaque;
else if(pkt->dts != AV_NOPTS_VALUE)
pts= pkt->dts;
else
pts= 0;
pts *= av_q2d(video_time_base); ctx->reordered_opaque = pkt.pts;
if(avcodec_decode_video2(ctx, Frame, &frameFinished, &pkt) <= 0)
printf("video decoder error\n");
if(frameFinished) if(frameFinished)
{ {
while( frames[dfx].ready != 0 ) AVPicture *dst_pic;
yield();
pict.data[0] = frames[dfx].frame->data[0];
pict.data[1] = frames[dfx].frame->data[1];
pict.data[2] = frames[dfx].frame->data[2];
pict.data[3] = NULL;
pict.linesize[0] = frames[dfx].frame->linesize[0]; if( pkt.dts == AV_NOPTS_VALUE &&
pict.linesize[1] = frames[dfx].frame->linesize[1]; Frame->reordered_opaque != AV_NOPTS_VALUE)
pict.linesize[2] = frames[dfx].frame->linesize[2]; pts = Frame->reordered_opaque;
pict.linesize[3] = 0; else if(pkt.dts != AV_NOPTS_VALUE)
pts= pkt.dts;
else
pts= 0;
data[0] = Frame->data[0]; // pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
data[1] = Frame->data[1]; // Frame, "best_effort_timestamp");
data[2] = Frame->data[2];
data[3] = NULL;
sws_scale(cvt_ctx, data, Frame->linesize, 0, ctx->height, // if (pts == AV_NOPTS_VALUE)
pict.data, pict.linesize); // pts = 0;
pts *= av_q2d(video_time_base);
dst_pic = &frames[dfx].picture;
av_image_copy(dst_pic->data, dst_pic->linesize, Frame->data,
Frame->linesize, ctx->pix_fmt, ctx->width, ctx->height);
frames[dfx].pts = pts*1000.0; frames[dfx].pts = pts*1000.0;
frames[dfx].ready = 1; frames[dfx].ready = 1;
dfx++; dfx++;
dfx&= 7; dfx&= 3;
}; };
av_free_packet(&pkt);
return 0; return 1;
} }
extern volatile uint32_t status; extern volatile uint32_t status;
rect_t win_rect;
typedef unsigned int color_t; int check_events()
typedef unsigned int count_t;
typedef unsigned int u32_t;
static void DrawWindow(int x, int y, int w, int h, char *name,
color_t workcolor, u32_t style)
{
__asm__ __volatile__(
"int $0x40"
::"a"(0),
"b"((x << 16) | (w & 0xFFFF)),
"c"((y << 16) | (h & 0xFFFF)),
"d"((style << 24) | (workcolor & 0xFFFFFF)),
"D"(name));
};
static int check_events()
{ {
int ev; int ev;
@ -189,8 +155,11 @@ static int check_events()
switch(ev) switch(ev)
{ {
case 1: case 1:
DrawWindow(10, 10, width+9, height+26, NULL, 0x000000,0x74); render_adjust_size(render);
BeginDraw();
DrawWindow(0,0,0,0, NULL, 0x000000,0x73);
EndDraw();
break; break;
case 3: case 3:
@ -202,15 +171,18 @@ static int check_events()
} }
extern char __cmdline[]; extern char *movie_file;
void video_thread(void *param) int video_thread(void *param)
{ {
char *path; rect_t rc;
AVCodecContext *ctx = param;
path = strrchr(__cmdline,'/')+1; BeginDraw();
DrawWindow(10, 10, width+9, height+26, movie_file, 0x000000,0x73);
EndDraw();
DrawWindow(10, 10, width+9, height+26, path, 0x000000,0x74); render_adjust_size(render);
while( status != 0) while( status != 0)
{ {
@ -223,21 +195,22 @@ void video_thread(void *param)
{ {
ctime = get_master_clock(); ctime = get_master_clock();
fdelay = (frames[vfx].pts - ctime); fdelay = (frames[vfx].pts - ctime);
// printf("ctime %f pts %f delay %f\n",
// ctime, frames[vfx].pts, fdelay); // printf("pts %f time %f delay %f\n",
// frames[vfx].pts, ctime, fdelay);
if(fdelay < 0.0 ) if(fdelay < 0.0 )
{ {
int next_vfx; int next_vfx;
fdelay = 0; fdelay = 0;
next_vfx = (vfx+1) & 7; next_vfx = (vfx+1) & 3;
if( frames[next_vfx].ready == 1 ) if( frames[next_vfx].ready == 1 )
{ {
if(frames[next_vfx].pts <= ctime) if(frames[next_vfx].pts <= ctime)
{ {
frames[vfx].ready = 0; // skip this frame frames[vfx].ready = 0; // skip this frame
vfx++; vfx++;
vfx&= 7; vfx&= 3;
} }
else else
{ {
@ -246,7 +219,7 @@ void video_thread(void *param)
{ {
frames[vfx].ready = 0; // skip this frame frames[vfx].ready = 0; // skip this frame
vfx++; vfx++;
vfx&= 7; vfx&= 3;
fdelay = (frames[next_vfx].pts - ctime); fdelay = (frames[next_vfx].pts - ctime);
} }
} }
@ -258,15 +231,259 @@ void video_thread(void *param)
delay( (uint32_t)(fdelay/10.0)); delay( (uint32_t)(fdelay/10.0));
}; };
draw_bitmap(frames[vfx].buffer, 0, 0, width, height); // blit_bitmap(&frames[vfx].bitmap, 5, 22, width, height);
// frames[vfx].frame->linesize[0]);
render->draw(render, &frames[vfx].picture);
frames[vfx].ready = 0; frames[vfx].ready = 0;
vfx++; vfx++;
vfx&= 7; vfx&= 3;
} }
else else
{ {
yield(); yield();
}; };
}; };
return 0;
}; };
void draw_hw_picture(render_t *render, AVPicture *picture);
void draw_sw_picture(render_t *render, AVPicture *picture);
render_t *create_render(uint32_t width, uint32_t height,
uint32_t ctx_format, uint32_t flags)
{
render_t *ren;
render = (render_t*)malloc(sizeof(*ren));
memset(ren, 0, sizeof(*ren));
render->ctx_width = width;
render->ctx_height = height;
render->ctx_format = ctx_format;
mutex_lock(&driver_lock);
render->caps = InitPixlib(flags);
mutex_unlock(&driver_lock);
if(render->caps==0)
{
printf("FPlay render engine: Hardware acceleration disabled\n");
render->draw = draw_sw_picture;
}
else
{
render->target = 0;
render->draw = draw_hw_picture;
};
render->state = EMPTY;
return render;
};
int render_set_size(render_t *render, int width, int height)
{
int i;
render->win_width = width;
render->win_height = height;
render->win_state = NORMAL;
// printf("%s %dx%d\n",__FUNCTION__, width, height);
if(render->state == EMPTY)
{
if(render->caps & HW_TEX_BLIT)
{
for( i=0; i < 4; i++)
{
render->bitmap[i].width = render->ctx_width;
render->bitmap[i].height = render->ctx_height;
if( create_bitmap(&render->bitmap[i]) != 0 )
{
status = 0;
/*
* Epic fail. Need exit_thread() here
*
*/
return 0;
};
}
}
else
{
render->bitmap[0].width = width;
render->bitmap[0].height = height;
if( create_bitmap(&render->bitmap[0]) != 0 )
return 0;
};
render->state = INIT;
return 0;
};
if(render->caps & HW_TEX_BLIT) /* hw scaler */
return 0;
render->bitmap[0].width = width;
render->bitmap[0].height = height;
resize_bitmap(&render->bitmap[0]);
return 0;
};
void render_adjust_size(render_t *render)
{
char proc_info[1024];
uint32_t right, bottom, new_w, new_h;
uint32_t s, sw, sh;
uint8_t state;
get_proc_info(proc_info);
right = *(uint32_t*)(proc_info+62)+1;
bottom = *(uint32_t*)(proc_info+66)+1;
state = *(uint8_t*)(proc_info+70);
if(state & 2)
{ render->win_state = MINIMIZED;
return;
}
if(state & 4)
{
render->win_state = ROLLED;
return;
};
render->win_state = NORMAL;
if( right == render->win_width &&
bottom == render->win_height)
return;
new_w = bottom*render->ctx_width/render->ctx_height;
new_h = right*render->ctx_height/render->ctx_width;
// printf("right %d bottom %d\n", right, bottom);
// printf("new_w %d new_h %d\n", new_w, new_h);
s = right * bottom;
sw = right * new_h;
sh = bottom * new_w;
if( abs(s-sw) > abs(s-sh))
new_h = bottom;
else
new_w = right;
if(new_w < 64)
{
new_w = 64;
new_h = 64*render->ctx_height/render->ctx_width;
};
__asm__ __volatile__(
"int $0x40"
::"a"(67), "b"(-1), "c"(-1),
"d"(new_w+9),"S"(new_h+26)
:"memory" );
render_set_size(render, new_w, new_h);
};
void draw_hw_picture(render_t *render, AVPicture *picture)
{
int dst_width, dst_height;
uint8_t *data[4];
int linesize[4];
if(render->win_state != NORMAL)
return;
if(render->caps & HW_TEX_BLIT)
{
dst_width = render->ctx_width;
dst_height = render->ctx_height;
}
else
{
dst_width = render->win_width;
dst_height = render->win_height;
};
cvt_ctx = sws_getCachedContext(cvt_ctx,
render->ctx_width, render->ctx_height, render->ctx_format,
dst_width, dst_height, PIX_FMT_BGRA,
SWS_FAST_BILINEAR, NULL, NULL, NULL);
if(cvt_ctx == NULL)
{
printf("Cannot initialize the conversion context!\n");
return ;
};
// printf("sws_getCachedContext\n");
data[0] = render->bitmap[render->target].data;
data[1] = render->bitmap[render->target].data+1;
data[2] = render->bitmap[render->target].data+2;
data[3] = render->bitmap[render->target].data+3;
linesize[0] = render->bitmap[render->target].pitch;
linesize[1] = render->bitmap[render->target].pitch;
linesize[2] = render->bitmap[render->target].pitch;
linesize[3] = render->bitmap[render->target].pitch;
sws_scale(cvt_ctx, (const uint8_t* const *)picture->data,
picture->linesize, 0, render->ctx_height, data, linesize);
// printf("sws_scale\n");
blit_bitmap(&render->bitmap[render->target], 5, 22,
render->win_width, render->win_height);
// printf("blit_bitmap\n");
delay(2);
render->target++;
render->target&= 3;
}
void draw_sw_picture(render_t *render, AVPicture *picture)
{
uint8_t *data[4];
int linesize[4];
if(render->win_state != NORMAL)
return;
cvt_ctx = sws_getCachedContext(cvt_ctx,
render->ctx_width, render->ctx_height,
render->ctx_format,
render->win_width, render->win_height,
PIX_FMT_BGRA, SWS_FAST_BILINEAR, NULL, NULL, NULL);
if(cvt_ctx == NULL)
{
printf("Cannot initialize the conversion context!\n");
return ;
}
data[0] = render->bitmap[0].data;
data[1] = render->bitmap[0].data+1;
data[2] = render->bitmap[0].data+2;
data[3] = render->bitmap[0].data+3;
linesize[0] = render->bitmap[0].pitch;
linesize[1] = render->bitmap[0].pitch;
linesize[2] = render->bitmap[0].pitch;
linesize[3] = render->bitmap[0].pitch;
sws_scale(cvt_ctx, (const uint8_t* const *)picture->data,
picture->linesize, 0, render->ctx_height, data, linesize);
blit_bitmap(&render->bitmap[0], 5, 22,
render->win_width, render->win_height);
}