Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 1685 → Rev 1696

/programs/media/Fplay/audio.c
0,0 → 1,240
 
#include <stdint.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
 
#include <stdio.h>
#include <string.h>
#include "sound.h"
#include "fplay.h"
 
 
astream_t astream;
 
static SNDBUF hBuff;
 
extern volatile uint32_t status;
 
void audio_thread(void *param);
 
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;
 
int init_audio(int format)
{
int err;
int version =-1;
char *errstr;
 
if((err = InitSound(&version)) !=0 )
{
errstr = "Sound service not installed\n\r";
goto exit_whith_error;
}
printf("sound version 0x%x\n", version);
 
if( (SOUND_VERSION>(version&0xFFFF)) ||
(SOUND_VERSION<(version >> 16)))
{
errstr = "Sound service version mismatch\n\r";
goto exit_whith_error;
}
 
snd_format = format;
 
asm volatile ( "xchgw %bx, %bx");
 
create_thread(audio_thread, 0, 163840);
 
return 1;
 
exit_whith_error:
 
printf(errstr);
return 0;
};
 
static uint64_t samples_lost;
static double audio_delta;
 
double get_master_clock()
{
double tstamp;
 
GetTimeStamp(hBuff, &tstamp);
return tstamp - audio_delta;
};
 
 
void audio_thread(void *param)
{
SND_EVENT evnt;
int buffsize;
int samples;
int err;
char *errstr;
 
 
if((err = CreateBuffer(snd_format|PCM_RING,0, &hBuff)) != 0)
{
errstr = "Cannot create sound buffer\n\r";
goto exit_whith_error;
};
 
SetVolume(hBuff,-1000,-1000);
 
if((err = GetBufferSize(hBuff, &buffsize)) != 0)
{
errstr = "Cannot get buffer size\n\r";
goto exit_whith_error;
};
 
buffsize = buffsize/2;
 
samples = buffsize/4;
 
while( (astream.count < buffsize*2) &&
(status != 0) )
yield();
 
spinlock_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);
};
 
if((err = PlayBuffer(hBuff, 0)) !=0 )
{
errstr = "Cannot play buffer\n\r";
goto exit_whith_error;
};
 
 
#ifdef BLACK_MAGIC_SOUND
 
while( status != 0)
{
uint32_t offset;
 
GetNotify(&evnt);
 
if(evnt.code != 0xFF000001)
{
printf("invalid event code %d\n\r", evnt.code);
continue;
}
 
if(evnt.stream != hBuff)
{
printf("invalid stream %x hBuff= %x\n\r",
evnt.stream, hBuff);
continue;
}
 
GetTimeStamp(hBuff, &audio_delta);
samples_lost = audio_delta*sample_rate/1000;
 
offset = evnt.offset;
 
spinlock_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);
};
break;
};
#endif
 
printf("initial audio delta %f\n", audio_delta);
 
while( status != 0)
{
uint32_t offset;
double event_stamp, wait_stamp;
int too_late = 0;
 
GetNotify(&evnt);
 
if(evnt.code != 0xFF000001)
{
printf("invalid event code %d\n\r", evnt.code);
continue;
}
 
if(evnt.stream != hBuff)
{
printf("invalid stream %x hBuff= %x\n\r",
evnt.stream, hBuff);
continue;
};
 
GetTimeStamp(hBuff, &event_stamp);
 
offset = evnt.offset;
 
while( (astream.count < buffsize) &&
(status != 0) )
{
yield();
GetTimeStamp(hBuff, &wait_stamp);
if( (wait_stamp - event_stamp) >
samples*1500/sample_rate )
{
samples_lost+= samples;
audio_delta = (double)samples_lost*1000/sample_rate;
// printf("audio delta %f\n", audio_delta);
too_late = 1;
break;
}
};
 
if((too_late == 1) || (status == 0))
continue;
 
spinlock_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);
}
 
return;
 
exit_whith_error:
 
printf(errstr);
return ;
 
};
 
/programs/media/Fplay/fplay.c
0,0 → 1,256
 
#include <stdint.h>
 
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
 
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include "sound.h"
#include "fplay.h"
 
volatile uint32_t status = 1;
 
uint32_t win_width, win_height;
 
void decoder();
 
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodecContext *aCodecCtx;
AVCodec *pCodec;
AVCodec *aCodec;
AVFrame *pFrame;
int videoStream;
int audioStream;
 
int have_sound = 0;
 
 
uint8_t *decoder_buffer;
extern int sample_rate;
 
int main( int argc, char *argv[])
{
int i;
 
if(argc < 2) {
printf("Please provide a movie file\n");
return -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)
{
printf("Cannot open file %s\n\r", argv[1]);
return -1; // Couldn't open file
};
 
// __asm__ __volatile__("int3");
 
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0)
{
printf("Cannot find streams\n\r");
return -1;
};
 
// __asm__ __volatile__("int3");
 
// dump_format(pFormatCtx, 0, argv[1], 0);
 
// Find the first video stream
videoStream=-1;
audioStream=-1;
for(i=0; i < pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO
&& videoStream < 0)
{
videoStream=i;
video_time_base = pFormatCtx->streams[i]->time_base;
 
}
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO &&
audioStream < 0)
{
audioStream=i;
}
}
 
if(videoStream==-1)
{
printf("Video stream not detected\n\r");
return -1; // Didn't find a video stream
}
 
 
// 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");
return -1; // Codec not found
}
// Open codec
if(avcodec_open(pCodecCtx, pCodec) < 0)
{
printf("Cannot open video codec\n\r");
return -1; // Could not open codec
};
 
if (aCodecCtx->channels > 0)
aCodecCtx->request_channels = FFMIN(2, aCodecCtx->channels);
else
aCodecCtx->request_channels = 2;
 
aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
 
if(aCodec)
{
if(avcodec_open(aCodecCtx, aCodec) >= 0 )
{
WAVEHEADER whdr;
int fmt;
 
printf("audio stream rate %d channels %d\n",
aCodecCtx->sample_rate, aCodecCtx->channels);
 
whdr.riff_id = 0x46464952;
whdr.riff_format = 0x45564157;
whdr.wFormatTag = 0x01;
whdr.nSamplesPerSec = aCodecCtx->sample_rate;
whdr.nChannels = aCodecCtx->channels;
whdr.wBitsPerSample = 16;
 
sample_rate = aCodecCtx->sample_rate;
 
fmt = test_wav(&whdr);
 
if( init_audio(fmt) )
{
decoder_buffer = (uint8_t*)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE);
if( decoder_buffer != NULL )
{
astream.lock = 0;
astream.count = 0;
astream.buffer = (char *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE*8);
if( astream.buffer != NULL )
have_sound = 1;
else
av_free(decoder_buffer);
}
if( have_sound == 0)
{
printf("Not enough memory for audio buffers\n");
}
}
}
else printf("Cannot open audio codec\n\r");
}
else printf("Unsupported audio codec!\n");
 
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
// avcodec_close(pCodecCtx);
 
// Close the video file
// av_close_input_file(pFormatCtx);
 
//__asm__ __volatile__("int3");
 
return 0;
}
 
void decoder()
{
AVPacket packet;
 
while(av_read_frame(pFormatCtx, &packet) >=0 )
{
if(packet.stream_index==videoStream)
{
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;
audio_size = packet.size;
 
while(audio_size > 0)
{
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);
};
};
 
 
__int64 _lseeki64(int fd, __int64 offset, int origin )
{
int off = offset;
return lseek(fd, off, origin);
}
 
 
 
/programs/media/Fplay/fplay.h
0,0 → 1,79
 
#define BLACK_MAGIC_SOUND
#define BLACK_MAGIC_VIDEO
 
typedef struct
{
volatile uint32_t lock;
char *buffer;
volatile uint32_t count;
}astream_t;
 
typedef struct
{
unsigned int code;
unsigned int sender;
unsigned int stream;
unsigned int offset;
unsigned int size;
unsigned int unused[2];
}SND_EVENT;
 
extern astream_t astream;
extern AVRational video_time_base;
 
int init_audio(int format);
int init_video(AVCodecContext *ctx);
int decode_video(AVCodecContext *ctx, AVPacket *pkt);
double get_master_clock();
 
 
int create_thread(void (*proc)(void *param), void *param, int stack_size);
 
void spinlock_lock(volatile uint32_t *val);
 
static inline void spinlock_unlock(volatile uint32_t *val)
{
*val = 0;
}
 
static inline void GetNotify(void *event)
{
__asm__ __volatile__ (
"int $0x40"
::"a"(68),"b"(14),"c"(event));
}
 
static inline uint32_t check_os_event()
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(11));
return val;
};
 
static inline uint32_t get_os_button()
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(17));
return val>>8;
};
 
static inline void yield(void)
{
__asm__ __volatile__(
"int $0x40"
::"a"(68), "b"(1));
};
 
static inline void delay(uint32_t time)
{
__asm__ __volatile__(
"int $0x40"
::"a"(5), "b"(time));
};
/programs/media/Fplay/sound.h
0,0 → 1,138
 
#ifndef _SOUND_H_
#define _SOUND_H_
 
#ifdef __cplusplus
extern "C"
{
#endif
 
#define SOUND_VERSION 0x0101
#define PCM_ALL 0
 
#define PCM_OUT 0x08000000
#define PCM_RING 0x10000000
#define PCM_STATIC 0x20000000
#define PCM_FLOAT 0x40000000
#define PCM_FILTER 0x80000000
 
#define PCM_2_16_48 1
#define PCM_1_16_48 2
#define PCM_2_16_44 3
#define PCM_1_16_44 4
#define PCM_2_16_32 5
#define PCM_1_16_32 6
#define PCM_2_16_24 7
#define PCM_1_16_24 8
#define PCM_2_16_22 9
#define PCM_1_16_22 10
#define PCM_2_16_16 11
#define PCM_1_16_16 12
#define PCM_2_16_12 13
#define PCM_1_16_12 14
#define PCM_2_16_11 15
#define PCM_1_16_11 16
#define PCM_2_16_8 17
#define PCM_1_16_8 18
#define PCM_2_8_48 19
#define PCM_1_8_48 20
#define PCM_2_8_44 21
#define PCM_1_8_44 22
#define PCM_2_8_32 23
#define PCM_1_8_32 24
#define PCM_2_8_24 25
#define PCM_1_8_24 26
#define PCM_2_8_22 27
#define PCM_1_8_22 28
#define PCM_2_8_16 29
#define PCM_1_8_16 30
#define PCM_2_8_12 31
#define PCM_1_8_12 32
#define PCM_2_8_11 33
#define PCM_1_8_11 34
#define PCM_2_8_8 35
#define PCM_1_8_8 36
 
#define SRV_GETVERSION 0
#define SND_CREATE_BUFF 1
#define SND_DESTROY_BUFF 2
#define SND_SETFORMAT 3
#define SND_GETFORMAT 4
#define SND_RESET 5
#define SND_SETPOS 6
#define SND_GETPOS 7
#define SND_SETBUFF 8
#define SND_OUT 9
#define SND_PLAY 10
#define SND_STOP 11
#define SND_SETVOLUME 12
#define SND_GETVOLUME 13
#define SND_SETPAN 14
#define SND_GETPAN 15
#define SND_GETBUFFSIZE 16
#define SND_GETFREESPACE 17
#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);
 
int _stdcall CreateBuffer(unsigned int format,int size,SNDBUF *buf);
int _stdcall DestroyBuffer(SNDBUF hBuff);
 
int _stdcall SetFormat(SNDBUF hBuff, unsigned int format);
int _stdcall GetFormat(SNDBUF hBuff, unsigned int *format);
 
int _stdcall ResetBuffer(SNDBUF hBuff, unsigned int flags);
int _stdcall SetBufferPos(SNDBUF hBuff, int offset);
int _stdcall GetBufferPos(SNDBUF hBuff, int *offset);
int _stdcall GetBufferSize(SNDBUF hBuff, int *size);
int _stdcall GetBufferFree(SNDBUF hBuff, int *free);
 
int _stdcall SetBuffer(SNDBUF hBuff,void* buff,
int offs, int size);
int _stdcall WaveOut(SNDBUF hBuff,void *buff, int size);
int _stdcall PlayBuffer(SNDBUF hBuff,unsigned int flags);
int _stdcall StopBuffer(SNDBUF hBuff);
 
int _stdcall SetVolume(SNDBUF hBuff, int left, int right);
int _stdcall GetVolume(SNDBUF hBuff, int *left, int *right);
int _stdcall SetPan(SNDBUF hBuff, int pan);
int _stdcall GetPan(SNDBUF hBuff, int *pan);
 
int _stdcall GetMasterVol(int* vol);
int _stdcall SetMasterVol(int vol);
 
int _stdcall SetTimeBase(SNDBUF hBuff, double base);
int _stdcall GetTimeStamp(SNDBUF hBuff, double *stamp);
 
unsigned int _stdcall test_wav(WAVEHEADER *hdr);
 
#ifdef __cplusplus
extern "C"
}
#endif
 
#endif //_SOUND_H_
/programs/media/Fplay/video.c
0,0 → 1,272
 
#include <stdint.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.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;
double pts;
volatile int ready;
}vframe_t;
 
vframe_t frames[8];
 
struct SwsContext *cvt_ctx;
 
int vfx = 0;
int dfx = 0;
 
int width;
int height;
 
AVRational video_time_base;
AVFrame *Frame;
 
int init_video(AVCodecContext *ctx)
{
uint32_t size;
int i;
 
width = ctx->width;
height = ctx->height;
 
printf("w = %d h = %d\n\r", width, height);
 
Frame = avcodec_alloc_frame();
if ( Frame == NULL )
{
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);
 
return 1;
};
 
int frameFinished=0;
 
int decode_video(AVCodecContext *ctx, AVPacket *pkt)
{
double pts;
AVPicture pict;
const uint8_t *data[4];
double av_time;
 
// __asm__("int3");
 
if(avcodec_decode_video(ctx, Frame, &frameFinished,
pkt->data, pkt->size) <= 0)
printf("decode error\n");
 
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;
 
pts *= av_q2d(video_time_base);
 
if(frameFinished)
{
while( frames[dfx].ready != 0 )
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];
pict.linesize[1] = frames[dfx].frame->linesize[1];
pict.linesize[2] = frames[dfx].frame->linesize[2];
pict.linesize[3] = 0;
 
data[0] = Frame->data[0];
data[1] = Frame->data[1];
data[2] = Frame->data[2];
data[3] = NULL;
 
sws_scale(cvt_ctx, data, Frame->linesize, 0, ctx->height,
pict.data, pict.linesize);
 
frames[dfx].pts = pts*1000.0;
frames[dfx].ready = 1;
 
dfx++;
dfx&= 7;
};
 
return 0;
}
 
extern volatile uint32_t status;
 
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 ev;
 
ev = check_os_event();
 
switch(ev)
{
case 1:
DrawWindow(10, 10, width+9, height+26, NULL, 0x000000,0x74);
break;
 
case 3:
if(get_os_button()==1)
status = 0;
break;
};
return 1;
}
 
 
extern char __cmdline[];
 
void video_thread(void *param)
{
char *path;
 
path = strrchr(__cmdline,'/')+1;
 
DrawWindow(10, 10, width+9, height+26, path, 0x000000,0x74);
 
while( status != 0)
{
double ctime;
double fdelay;
 
check_events();
 
if(frames[vfx].ready == 1 )
{
ctime = get_master_clock();
fdelay = (frames[vfx].pts - ctime);
// printf("ctime %f pts %f delay %f\n",
// ctime, frames[vfx].pts, fdelay);
 
if(fdelay < 0.0 )
{
int next_vfx;
fdelay = 0;
next_vfx = (vfx+1) & 7;
if( frames[next_vfx].ready == 1 )
{
if(frames[next_vfx].pts <= ctime)
{
frames[vfx].ready = 0; // skip this frame
vfx++;
vfx&= 7;
}
else
{
if( (frames[next_vfx].pts - ctime) <
( ctime - frames[vfx].pts) )
{
frames[vfx].ready = 0; // skip this frame
vfx++;
vfx&= 7;
fdelay = (frames[next_vfx].pts - ctime);
}
}
};
};
 
if(fdelay > 10.0)
{
delay( (uint32_t)(fdelay/10.0));
};
 
draw_bitmap(frames[vfx].buffer, 0, 0, width, height);
frames[vfx].ready = 0;
vfx++;
vfx&= 7;
}
else
{
yield();
};
};
};
 
/programs/media/Fplay
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property