forked from KolibriOS/kolibrios
sna scaler
git-svn-id: svn://kolibrios.org@2349 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
4a23260a83
commit
84726c7e7b
@ -14,32 +14,12 @@ astream_t astream;
|
||||
|
||||
static SNDBUF hBuff;
|
||||
|
||||
extern uint8_t *decoder_buffer;
|
||||
|
||||
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;
|
||||
int sample_rate;
|
||||
@ -50,11 +30,17 @@ int init_audio(int format)
|
||||
int version =-1;
|
||||
char *errstr;
|
||||
|
||||
mutex_lock(&driver_lock);
|
||||
|
||||
if((err = InitSound(&version)) !=0 )
|
||||
{
|
||||
mutex_unlock(&driver_lock);
|
||||
errstr = "Sound service not installed\n\r";
|
||||
goto exit_whith_error;
|
||||
}
|
||||
};
|
||||
|
||||
mutex_unlock(&driver_lock);
|
||||
|
||||
printf("sound version 0x%x\n", version);
|
||||
|
||||
if( (SOUND_VERSION>(version&0xFFFF)) ||
|
||||
@ -66,8 +52,6 @@ int init_audio(int format)
|
||||
|
||||
snd_format = format;
|
||||
|
||||
asm volatile ( "xchgw %bx, %bx");
|
||||
|
||||
create_thread(audio_thread, 0, 163840);
|
||||
|
||||
return 1;
|
||||
@ -89,8 +73,51 @@ double get_master_clock()
|
||||
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;
|
||||
int buffsize;
|
||||
@ -121,13 +148,13 @@ void audio_thread(void *param)
|
||||
(status != 0) )
|
||||
yield();
|
||||
|
||||
spinlock_lock(&astream.lock);
|
||||
mutex_lock(&astream.lock);
|
||||
{
|
||||
SetBuffer(hBuff, astream.buffer, 0, buffsize);
|
||||
astream.count -= buffsize;
|
||||
if(astream.count)
|
||||
memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
|
||||
spinlock_unlock(&astream.lock);
|
||||
mutex_unlock(&astream.lock);
|
||||
};
|
||||
|
||||
if((err = PlayBuffer(hBuff, 0)) !=0 )
|
||||
@ -163,13 +190,13 @@ void audio_thread(void *param)
|
||||
|
||||
offset = evnt.offset;
|
||||
|
||||
spinlock_lock(&astream.lock);
|
||||
mutex_lock(&astream.lock);
|
||||
{
|
||||
SetBuffer(hBuff, astream.buffer, offset, buffsize);
|
||||
astream.count -= buffsize;
|
||||
if(astream.count)
|
||||
memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
|
||||
spinlock_unlock(&astream.lock);
|
||||
mutex_unlock(&astream.lock);
|
||||
};
|
||||
break;
|
||||
};
|
||||
@ -221,20 +248,23 @@ void audio_thread(void *param)
|
||||
if((too_late == 1) || (status == 0))
|
||||
continue;
|
||||
|
||||
spinlock_lock(&astream.lock);
|
||||
mutex_lock(&astream.lock);
|
||||
SetBuffer(hBuff, astream.buffer, offset, buffsize);
|
||||
astream.count -= buffsize;
|
||||
if(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:
|
||||
|
||||
printf(errstr);
|
||||
return ;
|
||||
return -1;
|
||||
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sound.h"
|
||||
#include "fplay.h"
|
||||
|
||||
@ -29,9 +31,13 @@ int audioStream;
|
||||
|
||||
int have_sound = 0;
|
||||
|
||||
|
||||
uint8_t *decoder_buffer;
|
||||
extern int sample_rate;
|
||||
char *movie_file;
|
||||
|
||||
|
||||
queue_t q_video;
|
||||
queue_t q_audio;
|
||||
|
||||
int main( int argc, char *argv[])
|
||||
{
|
||||
@ -42,24 +48,23 @@ int main( int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
movie_file = argv[1];
|
||||
/* register all codecs, demux and protocols */
|
||||
|
||||
avcodec_register_all();
|
||||
avdevice_register_all();
|
||||
av_register_all();
|
||||
|
||||
|
||||
// Open video file
|
||||
if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
|
||||
if( avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) < 0)
|
||||
{
|
||||
printf("Cannot open file %s\n\r", argv[1]);
|
||||
return -1; // Couldn't open file
|
||||
};
|
||||
|
||||
// __asm__ __volatile__("int3");
|
||||
printf("%s\n\r", __FUNCTION__);
|
||||
|
||||
// Retrieve stream information
|
||||
if(av_find_stream_info(pFormatCtx)<0)
|
||||
if(avformat_find_stream_info(pFormatCtx, NULL)<0)
|
||||
{
|
||||
printf("Cannot find streams\n\r");
|
||||
return -1;
|
||||
@ -74,14 +79,14 @@ int main( int argc, char *argv[])
|
||||
audioStream=-1;
|
||||
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=i;
|
||||
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=i;
|
||||
@ -94,22 +99,24 @@ int main( int argc, char *argv[])
|
||||
return -1; // Didn't find a video stream
|
||||
}
|
||||
|
||||
// __asm__ __volatile__("int3");
|
||||
|
||||
// Get a pointer to the codec context for the video stream
|
||||
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
|
||||
|
||||
aCodecCtx=pFormatCtx->streams[audioStream]->codec;
|
||||
|
||||
// Find the decoder for the video stream
|
||||
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
|
||||
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
|
||||
}
|
||||
// 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
|
||||
};
|
||||
|
||||
@ -122,7 +129,7 @@ int main( int argc, char *argv[])
|
||||
|
||||
if(aCodec)
|
||||
{
|
||||
if(avcodec_open(aCodecCtx, aCodec) >= 0 )
|
||||
if(avcodec_open2(aCodecCtx, aCodec, NULL) >= 0 )
|
||||
{
|
||||
WAVEHEADER whdr;
|
||||
int fmt;
|
||||
@ -143,7 +150,7 @@ int main( int argc, char *argv[])
|
||||
|
||||
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 )
|
||||
{
|
||||
astream.lock = 0;
|
||||
@ -167,20 +174,14 @@ int main( int argc, char *argv[])
|
||||
if( !init_video(pCodecCtx))
|
||||
return 0;
|
||||
|
||||
// Assign appropriate parts of buffer to image planes in pFrameRGB
|
||||
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
|
||||
// of AVPicture
|
||||
|
||||
// __asm__ __volatile__("int3");
|
||||
|
||||
decoder();
|
||||
|
||||
status = 0;
|
||||
|
||||
|
||||
// Free the YUV frame
|
||||
av_free(pFrame);
|
||||
|
||||
|
||||
//__asm__ __volatile__("int3");
|
||||
|
||||
// Close the codec
|
||||
@ -196,61 +197,59 @@ int main( int argc, char *argv[])
|
||||
|
||||
void decoder()
|
||||
{
|
||||
int eof = 0;
|
||||
AVPacket packet;
|
||||
int ret;
|
||||
|
||||
while(av_read_frame(pFormatCtx, &packet) >=0 )
|
||||
while( status != 0 && !eof)
|
||||
{
|
||||
int err;
|
||||
|
||||
// __asm__ __volatile__("int3");
|
||||
|
||||
if(q_video.size+q_audio.size < 16*1024*1024)
|
||||
{
|
||||
err = av_read_frame(pFormatCtx, &packet);
|
||||
if( err < 0)
|
||||
{
|
||||
eof = 1;
|
||||
if (err != AVERROR_EOF)
|
||||
printf("av_read_frame: error %x\n", err);
|
||||
continue;
|
||||
}
|
||||
if(packet.stream_index==videoStream)
|
||||
{
|
||||
decode_video(pCodecCtx, &packet);
|
||||
put_packet(&q_video, &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;
|
||||
audio_size = packet.size;
|
||||
|
||||
while(audio_size > 0)
|
||||
put_packet(&q_audio, &packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||
|
||||
len = avcodec_decode_audio2(aCodecCtx,(int16_t*)decoder_buffer,
|
||||
&data_size, audio_data, audio_size);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
// Free the packet that was allocated by av_read_frame
|
||||
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;
|
||||
|
||||
__int64 _lseeki64(int fd, __int64 offset, int origin )
|
||||
while(status != 0 && ret)
|
||||
{
|
||||
int off = offset;
|
||||
return lseek(fd, off, origin);
|
||||
}
|
||||
|
||||
|
||||
ret = decode_video(pCodecCtx, &q_video);
|
||||
ret |= decode_audio(aCodecCtx, &q_audio);
|
||||
delay(1);
|
||||
};
|
||||
delay(50);
|
||||
status = 0;
|
||||
printf("status = 0\n");
|
||||
delay(200);
|
||||
};
|
||||
|
||||
|
@ -2,6 +2,48 @@
|
||||
#define BLACK_MAGIC_SOUND
|
||||
#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
|
||||
{
|
||||
volatile uint32_t lock;
|
||||
@ -19,20 +61,54 @@ typedef struct
|
||||
unsigned int unused[2];
|
||||
}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 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 audio_thread(void *param);
|
||||
|
||||
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();
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
@ -77,3 +153,59 @@ static inline void delay(uint32_t time)
|
||||
"int $0x40"
|
||||
::"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);
|
||||
|
||||
|
||||
|
327
programs/media/Fplay/pixlib2.c
Normal file
327
programs/media/Fplay/pixlib2.c
Normal 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;
|
||||
};
|
||||
|
@ -74,27 +74,9 @@ extern "C"
|
||||
#define SND_SETTIMEBASE 18
|
||||
#define SND_GETTIMESTAMP 19
|
||||
|
||||
|
||||
#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;
|
||||
|
||||
int _stdcall InitSound(int *version);
|
||||
@ -127,6 +109,28 @@ int _stdcall SetMasterVol(int vol);
|
||||
|
||||
int _stdcall SetTimeBase(SNDBUF hBuff, double base);
|
||||
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);
|
||||
|
||||
|
98
programs/media/Fplay/utils.c
Normal file
98
programs/media/Fplay/utils.c
Normal 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;
|
||||
}
|
@ -3,44 +3,39 @@
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
#include "sound.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
|
||||
{
|
||||
AVFrame *frame;
|
||||
uint8_t *buffer;
|
||||
AVPicture picture;
|
||||
double pts;
|
||||
volatile int ready;
|
||||
}vframe_t;
|
||||
|
||||
vframe_t frames[8];
|
||||
vframe_t frames[4];
|
||||
|
||||
struct SwsContext *cvt_ctx;
|
||||
struct SwsContext *cvt_ctx = NULL;
|
||||
|
||||
int vfx = 0;
|
||||
int dfx = 0;
|
||||
|
||||
render_t *render;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
AVRational video_time_base;
|
||||
AVFrame *Frame;
|
||||
|
||||
volatile uint32_t driver_lock;
|
||||
|
||||
void get_client_rect(rect_t *rc);
|
||||
|
||||
|
||||
int init_video(AVCodecContext *ctx)
|
||||
{
|
||||
uint32_t size;
|
||||
int i;
|
||||
|
||||
width = ctx->width;
|
||||
@ -48,140 +43,111 @@ int init_video(AVCodecContext *ctx)
|
||||
|
||||
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();
|
||||
if ( Frame == NULL )
|
||||
{
|
||||
printf("Cannot alloc video frame\n\r");
|
||||
return 0;
|
||||
};
|
||||
|
||||
for( i=0; i < 4; i++)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// printf("alloc picture %d %d %x\n",
|
||||
// ctx->width, ctx->height, ctx->pix_fmt );
|
||||
|
||||
ret = avpicture_alloc(&frames[i].picture, ctx->pix_fmt,
|
||||
ctx->width, ctx->height);
|
||||
if ( ret != 0 )
|
||||
{
|
||||
printf("Cannot alloc video buffer\n\r");
|
||||
return 0;
|
||||
};
|
||||
|
||||
cvt_ctx = sws_getContext(
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = avpicture_get_size(PIX_FMT_RGB24, ctx->width, ctx->height);
|
||||
|
||||
for( i=0; i < 8; i++)
|
||||
{
|
||||
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);
|
||||
|
||||
frames[i].frame = frame;
|
||||
frames[i].buffer = buffer;
|
||||
frames[i].pts = 0;
|
||||
frames[i].ready = 0;
|
||||
continue;
|
||||
};
|
||||
};
|
||||
printf("Cannot alloc frame buffer\n\r");
|
||||
return 0;
|
||||
};
|
||||
|
||||
create_thread(video_thread, 0, 163840);
|
||||
create_thread(video_thread, ctx, 1024*1024);
|
||||
|
||||
delay(50);
|
||||
return 1;
|
||||
};
|
||||
|
||||
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;
|
||||
AVPicture pict;
|
||||
const uint8_t *data[4];
|
||||
double av_time;
|
||||
|
||||
// __asm__("int3");
|
||||
if(frames[dfx].ready != 0 )
|
||||
return 1;
|
||||
|
||||
if(avcodec_decode_video(ctx, Frame, &frameFinished,
|
||||
pkt->data, pkt->size) <= 0)
|
||||
printf("decode error\n");
|
||||
if( get_packet(qv, &pkt) == 0 )
|
||||
return 0;
|
||||
|
||||
if( pkt->dts == AV_NOPTS_VALUE &&
|
||||
Frame->reordered_opaque != AV_NOPTS_VALUE)
|
||||
pts= Frame->reordered_opaque;
|
||||
else if(pkt->dts != AV_NOPTS_VALUE)
|
||||
pts= pkt->dts;
|
||||
else
|
||||
pts= 0;
|
||||
frameFinished = 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)
|
||||
{
|
||||
while( frames[dfx].ready != 0 )
|
||||
yield();
|
||||
AVPicture *dst_pic;
|
||||
|
||||
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];
|
||||
pict.linesize[1] = frames[dfx].frame->linesize[1];
|
||||
pict.linesize[2] = frames[dfx].frame->linesize[2];
|
||||
pict.linesize[3] = 0;
|
||||
if( pkt.dts == AV_NOPTS_VALUE &&
|
||||
Frame->reordered_opaque != AV_NOPTS_VALUE)
|
||||
pts = Frame->reordered_opaque;
|
||||
else if(pkt.dts != AV_NOPTS_VALUE)
|
||||
pts= pkt.dts;
|
||||
else
|
||||
pts= 0;
|
||||
|
||||
data[0] = Frame->data[0];
|
||||
data[1] = Frame->data[1];
|
||||
data[2] = Frame->data[2];
|
||||
data[3] = NULL;
|
||||
// pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
|
||||
// Frame, "best_effort_timestamp");
|
||||
|
||||
sws_scale(cvt_ctx, data, Frame->linesize, 0, ctx->height,
|
||||
pict.data, pict.linesize);
|
||||
// if (pts == AV_NOPTS_VALUE)
|
||||
// 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].ready = 1;
|
||||
|
||||
dfx++;
|
||||
dfx&= 7;
|
||||
dfx&= 3;
|
||||
};
|
||||
av_free_packet(&pkt);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern volatile uint32_t status;
|
||||
rect_t win_rect;
|
||||
|
||||
typedef unsigned int color_t;
|
||||
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 check_events()
|
||||
{
|
||||
int ev;
|
||||
|
||||
@ -190,7 +156,10 @@ static int check_events()
|
||||
switch(ev)
|
||||
{
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
@ -223,21 +195,22 @@ void video_thread(void *param)
|
||||
{
|
||||
ctime = get_master_clock();
|
||||
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 )
|
||||
{
|
||||
int next_vfx;
|
||||
fdelay = 0;
|
||||
next_vfx = (vfx+1) & 7;
|
||||
next_vfx = (vfx+1) & 3;
|
||||
if( frames[next_vfx].ready == 1 )
|
||||
{
|
||||
if(frames[next_vfx].pts <= ctime)
|
||||
{
|
||||
frames[vfx].ready = 0; // skip this frame
|
||||
vfx++;
|
||||
vfx&= 7;
|
||||
vfx&= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -246,7 +219,7 @@ void video_thread(void *param)
|
||||
{
|
||||
frames[vfx].ready = 0; // skip this frame
|
||||
vfx++;
|
||||
vfx&= 7;
|
||||
vfx&= 3;
|
||||
fdelay = (frames[next_vfx].pts - ctime);
|
||||
}
|
||||
}
|
||||
@ -258,15 +231,259 @@ void video_thread(void *param)
|
||||
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;
|
||||
vfx++;
|
||||
vfx&= 7;
|
||||
vfx&= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user