forked from KolibriOS/kolibrios
Fplay source code.
git-svn-id: svn://kolibrios.org@1696 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
137b1fee08
commit
4f80db8269
240
programs/media/Fplay/audio.c
Normal file
240
programs/media/Fplay/audio.c
Normal file
@ -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 ;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
256
programs/media/Fplay/fplay.c
Normal file
256
programs/media/Fplay/fplay.c
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
79
programs/media/Fplay/fplay.h
Normal file
79
programs/media/Fplay/fplay.h
Normal file
@ -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));
|
||||||
|
};
|
138
programs/media/Fplay/sound.h
Normal file
138
programs/media/Fplay/sound.h
Normal file
@ -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_
|
272
programs/media/Fplay/video.c
Normal file
272
programs/media/Fplay/video.c
Normal file
@ -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();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user