Fplay: new init_decoder()/fini_decoder()
git-svn-id: svn://kolibrios.org@6144 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
3a7404eddd
commit
4b978f2310
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
NAME= Fplay
|
NAME= Fplay
|
||||||
|
|
||||||
FASM= fasm.exe
|
FASM= fasm.exe
|
||||||
@ -27,6 +26,7 @@ LDFLAGS = -static -nostdlib --stack 0x200000 -Map fplay.map -T$(SDK_DIR)/sources
|
|||||||
|
|
||||||
SOURCES = opendial.asm \
|
SOURCES = opendial.asm \
|
||||||
audio.c \
|
audio.c \
|
||||||
|
decoder.c \
|
||||||
fplay.c \
|
fplay.c \
|
||||||
vaapi.c \
|
vaapi.c \
|
||||||
video.c \
|
video.c \
|
||||||
|
@ -29,9 +29,6 @@ static int snd_format;
|
|||||||
int sample_rate;
|
int sample_rate;
|
||||||
|
|
||||||
static uint32_t samples_written = 0;
|
static uint32_t samples_written = 0;
|
||||||
double audio_base = -1.0;
|
|
||||||
|
|
||||||
double get_audio_base();
|
|
||||||
|
|
||||||
int init_audio(int format)
|
int init_audio(int format)
|
||||||
{
|
{
|
||||||
@ -128,14 +125,6 @@ int decode_audio(AVCodecContext *ctx, queue_t *qa)
|
|||||||
int data_size = av_samples_get_buffer_size(&plane_size, ctx->channels,
|
int data_size = av_samples_get_buffer_size(&plane_size, ctx->channels,
|
||||||
aFrame->nb_samples,
|
aFrame->nb_samples,
|
||||||
ctx->sample_fmt, 1);
|
ctx->sample_fmt, 1);
|
||||||
|
|
||||||
// if(audio_base == -1.0)
|
|
||||||
// {
|
|
||||||
// if (pkt.pts != AV_NOPTS_VALUE)
|
|
||||||
// audio_base = get_audio_base() * pkt.pts;
|
|
||||||
// printf("audio base %f\n", audio_base);
|
|
||||||
// };
|
|
||||||
|
|
||||||
pkt_tmp.data += len;
|
pkt_tmp.data += len;
|
||||||
pkt_tmp.size -= len;
|
pkt_tmp.size -= len;
|
||||||
|
|
||||||
@ -254,6 +243,7 @@ static void sync_audio(SNDBUF hbuff, int buffsize)
|
|||||||
|
|
||||||
int audio_thread(void *param)
|
int audio_thread(void *param)
|
||||||
{
|
{
|
||||||
|
vst_t *vst = param;
|
||||||
SND_EVENT evnt;
|
SND_EVENT evnt;
|
||||||
|
|
||||||
int buffsize;
|
int buffsize;
|
||||||
@ -306,11 +296,10 @@ int audio_thread(void *param)
|
|||||||
memcpy(astream.buffer, astream.buffer+buffsize*2, astream.count);
|
memcpy(astream.buffer, astream.buffer+buffsize*2, astream.count);
|
||||||
mutex_unlock(&astream.lock);
|
mutex_unlock(&astream.lock);
|
||||||
|
|
||||||
SetTimeBase(hBuff, audio_base);
|
SetTimeBase(hBuff, vst->audio_timer_base);
|
||||||
|
|
||||||
case PAUSE_2_PLAY:
|
case PAUSE_2_PLAY:
|
||||||
GetTimeStamp(hBuff, &last_time_stamp);
|
GetTimeStamp(hBuff, &last_time_stamp);
|
||||||
// printf("last audio time stamp %f\n", last_time_stamp);
|
|
||||||
|
|
||||||
if((err = PlayBuffer(hBuff, 0)) !=0 )
|
if((err = PlayBuffer(hBuff, 0)) !=0 )
|
||||||
{
|
{
|
||||||
@ -320,7 +309,6 @@ int audio_thread(void *param)
|
|||||||
active = 1;
|
active = 1;
|
||||||
sync_audio(hBuff, buffsize);
|
sync_audio(hBuff, buffsize);
|
||||||
sound_state = PLAY;
|
sound_state = PLAY;
|
||||||
// printf("render: set audio latency to %f\n", audio_delta);
|
|
||||||
|
|
||||||
/* breaktrough */
|
/* breaktrough */
|
||||||
|
|
||||||
@ -385,7 +373,7 @@ int audio_thread(void *param)
|
|||||||
if( active )
|
if( active )
|
||||||
{
|
{
|
||||||
ResetBuffer(hBuff, SND_RESET_ALL);
|
ResetBuffer(hBuff, SND_RESET_ALL);
|
||||||
audio_base = -1.0;
|
vst->audio_timer_valid = 0;
|
||||||
active = 0;
|
active = 0;
|
||||||
}
|
}
|
||||||
sound_state = STOP;
|
sound_state = STOP;
|
||||||
|
232
contrib/media/fplay/decoder.c
Normal file
232
contrib/media/fplay/decoder.c
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/imgutils.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <kos32sys.h>
|
||||||
|
#include "winlib/winlib.h"
|
||||||
|
|
||||||
|
#include "sound.h"
|
||||||
|
#include "fplay.h"
|
||||||
|
|
||||||
|
static struct decoder* init_ffmpeg_decoder(vst_t *vst)
|
||||||
|
{
|
||||||
|
AVCodecContext *vCtx = vst->vCtx;
|
||||||
|
struct decoder *decoder;
|
||||||
|
vframe_t *vframe;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
decoder = calloc(1, sizeof(struct decoder));
|
||||||
|
if(decoder == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
decoder->Frame = av_frame_alloc();
|
||||||
|
if(decoder->Frame == NULL)
|
||||||
|
goto err_0;
|
||||||
|
|
||||||
|
decoder->nframes = 4;
|
||||||
|
|
||||||
|
for(i = 0; i < decoder->nframes; i++)
|
||||||
|
{
|
||||||
|
vframe = &decoder->vframes[i];
|
||||||
|
|
||||||
|
ret = avpicture_alloc(&vframe->picture, vCtx->pix_fmt,
|
||||||
|
vCtx->width, vCtx->height);
|
||||||
|
if ( ret != 0 )
|
||||||
|
goto err_1;
|
||||||
|
|
||||||
|
vframe->format = vCtx->pix_fmt;
|
||||||
|
vframe->index = i;
|
||||||
|
vframe->pts = 0;
|
||||||
|
vframe->ready = 0;
|
||||||
|
list_add_tail(&vframe->list, &vst->input_list);
|
||||||
|
};
|
||||||
|
|
||||||
|
if(avcodec_open2(vCtx, vst->vCodec, NULL) < 0)
|
||||||
|
{
|
||||||
|
printf("Error while opening codec for input stream %d\n",
|
||||||
|
vst->vStream);
|
||||||
|
goto err_1;
|
||||||
|
};
|
||||||
|
|
||||||
|
decoder->name = vst->vCodec->name;
|
||||||
|
decoder->pix_fmt = vCtx->pix_fmt;
|
||||||
|
decoder->width = vCtx->width;
|
||||||
|
decoder->height = vCtx->height;
|
||||||
|
decoder->codec_id = vCtx->codec_id;
|
||||||
|
|
||||||
|
return decoder;
|
||||||
|
|
||||||
|
err_1:
|
||||||
|
for(i = i-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
vframe = &decoder->vframes[i];
|
||||||
|
avpicture_free(&vframe->picture);
|
||||||
|
};
|
||||||
|
av_frame_free(&decoder->Frame);
|
||||||
|
err_0:
|
||||||
|
free(decoder);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int init_video_decoder(vst_t *vst)
|
||||||
|
{
|
||||||
|
AVCodecContext *vCtx = vst->vCtx;
|
||||||
|
|
||||||
|
vst->vCodec = avcodec_find_decoder(vCtx->codec_id);
|
||||||
|
|
||||||
|
if(vst->vCodec == NULL)
|
||||||
|
{
|
||||||
|
printf("Unsupported codec with id %d for input stream %d\n",
|
||||||
|
vst->vCtx->codec_id, vst->vStream);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vst->decoder = va_init_decoder(vst);
|
||||||
|
if(vst->decoder == NULL)
|
||||||
|
vst->decoder = init_ffmpeg_decoder(vst);
|
||||||
|
|
||||||
|
if(vst->decoder != NULL)
|
||||||
|
{
|
||||||
|
printf("%dx%d %s %s%s decoder\n",
|
||||||
|
vst->decoder->width, vst->decoder->height,
|
||||||
|
av_get_pix_fmt_name(vst->decoder->pix_fmt),
|
||||||
|
vst->decoder->is_hw == 0 ? "ffmpeg ":"vaapi ",
|
||||||
|
vst->decoder->name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fini_video_decoder(vst_t *vst)
|
||||||
|
{
|
||||||
|
avcodec_close(vst->vCtx);
|
||||||
|
|
||||||
|
if(vst->decoder->is_hw != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(int i = 0; i < vst->decoder->nframes; i++)
|
||||||
|
{
|
||||||
|
vframe_t *vframe;
|
||||||
|
vframe = &vst->decoder->vframes[i];
|
||||||
|
avpicture_free(&vframe->picture);
|
||||||
|
};
|
||||||
|
av_frame_free(&vst->decoder->Frame);
|
||||||
|
free(vst->decoder);
|
||||||
|
};
|
||||||
|
|
||||||
|
static vframe_t *get_input_frame(vst_t *vst)
|
||||||
|
{
|
||||||
|
vframe_t *vframe = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&vst->input_lock);
|
||||||
|
if(!list_empty(&vst->input_list))
|
||||||
|
{
|
||||||
|
vframe = list_first_entry(&vst->input_list, vframe_t, list);
|
||||||
|
list_del(&vframe->list);
|
||||||
|
}
|
||||||
|
mutex_unlock(&vst->input_lock);
|
||||||
|
|
||||||
|
return vframe;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put_output_frame(vst_t *vst, vframe_t *vframe)
|
||||||
|
{
|
||||||
|
mutex_lock(&vst->output_lock);
|
||||||
|
if(list_empty(&vst->output_list))
|
||||||
|
list_add_tail(&vframe->list, &vst->output_list);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vframe_t *cur;
|
||||||
|
|
||||||
|
cur = list_first_entry(&vst->output_list,vframe_t,list);
|
||||||
|
if(vframe->pts < cur->pts)
|
||||||
|
list_add_tail(&vframe->list, &vst->output_list);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list_for_each_entry_reverse(cur,&vst->output_list,list)
|
||||||
|
{
|
||||||
|
if(vframe->pts > cur->pts)
|
||||||
|
{
|
||||||
|
list_add(&vframe->list, &cur->list);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
vst->frames_count++;
|
||||||
|
mutex_unlock(&vst->output_lock);
|
||||||
|
};
|
||||||
|
|
||||||
|
int decode_video(vst_t* vst)
|
||||||
|
{
|
||||||
|
struct decoder* decoder = vst->decoder;
|
||||||
|
double pts;
|
||||||
|
AVPacket pkt;
|
||||||
|
|
||||||
|
int frameFinished;
|
||||||
|
|
||||||
|
if(decoder->active_frame == NULL)
|
||||||
|
decoder->active_frame = get_input_frame(vst);
|
||||||
|
|
||||||
|
if(decoder->active_frame == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if( get_packet(&vst->q_video, &pkt) == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
frameFinished = 0;
|
||||||
|
|
||||||
|
mutex_lock(&vst->gpu_lock);
|
||||||
|
|
||||||
|
if(avcodec_decode_video2(vst->vCtx, decoder->Frame, &frameFinished, &pkt) <= 0)
|
||||||
|
printf("video decoder error\n");
|
||||||
|
|
||||||
|
if(frameFinished)
|
||||||
|
{
|
||||||
|
vframe_t *vframe = decoder->active_frame;
|
||||||
|
AVPicture *dst_pic;
|
||||||
|
|
||||||
|
if(decoder->is_hw)
|
||||||
|
pts = pkt.pts;
|
||||||
|
else
|
||||||
|
pts = av_frame_get_best_effort_timestamp(decoder->Frame);
|
||||||
|
|
||||||
|
pts*= av_q2d(vst->video_time_base);
|
||||||
|
|
||||||
|
dst_pic = &vframe->picture;
|
||||||
|
|
||||||
|
if(vframe->is_hw_pic == 0)
|
||||||
|
av_image_copy(dst_pic->data, dst_pic->linesize,
|
||||||
|
(const uint8_t**)decoder->Frame->data,
|
||||||
|
decoder->Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height);
|
||||||
|
else
|
||||||
|
va_create_planar(vst, vframe);
|
||||||
|
|
||||||
|
vframe->pts = pts*1000.0;
|
||||||
|
vframe->pkt_pts = pkt.pts*av_q2d(vst->video_time_base)*1000.0;
|
||||||
|
vframe->ready = 1;
|
||||||
|
|
||||||
|
put_output_frame(vst, vframe);
|
||||||
|
|
||||||
|
// printf("decoded index: %d pts: %f pkt_pts %f pkt_dts %f\n",
|
||||||
|
// vst->dfx, vst->vframe[vst->dfx].pts,
|
||||||
|
// vst->vframe[vst->dfx].pkt_pts, vst->vframe[vst->dfx].pkt_dts);
|
||||||
|
|
||||||
|
decoder->active_frame = NULL;
|
||||||
|
};
|
||||||
|
av_frame_unref(decoder->Frame);
|
||||||
|
mutex_unlock(&vst->gpu_lock);
|
||||||
|
|
||||||
|
av_free_packet(&pkt);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
@ -22,8 +22,6 @@ volatile enum player_state sound_state = STOP;
|
|||||||
|
|
||||||
uint32_t win_width, win_height;
|
uint32_t win_width, win_height;
|
||||||
|
|
||||||
int have_sound = 0;
|
|
||||||
|
|
||||||
uint8_t *decoder_buffer;
|
uint8_t *decoder_buffer;
|
||||||
extern int resampler_size;
|
extern int resampler_size;
|
||||||
extern int sample_rate;
|
extern int sample_rate;
|
||||||
@ -34,8 +32,6 @@ int64_t stream_duration;
|
|||||||
|
|
||||||
int threads_running = DECODER_THREAD;
|
int threads_running = DECODER_THREAD;
|
||||||
|
|
||||||
extern double audio_base;
|
|
||||||
|
|
||||||
|
|
||||||
int main( int argc, char *argv[])
|
int main( int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -70,7 +66,6 @@ int main( int argc, char *argv[])
|
|||||||
|
|
||||||
vst.fCtx->flags |= AVFMT_FLAG_GENPTS;
|
vst.fCtx->flags |= AVFMT_FLAG_GENPTS;
|
||||||
|
|
||||||
// Retrieve stream information
|
|
||||||
if(avformat_find_stream_info(vst.fCtx, NULL) < 0)
|
if(avformat_find_stream_info(vst.fCtx, NULL) < 0)
|
||||||
{
|
{
|
||||||
printf("Cannot find streams\n\r");
|
printf("Cannot find streams\n\r");
|
||||||
@ -89,7 +84,6 @@ int main( int argc, char *argv[])
|
|||||||
|
|
||||||
stream_duration = vst.fCtx->duration;
|
stream_duration = vst.fCtx->duration;
|
||||||
|
|
||||||
// Find the first video stream
|
|
||||||
vst.vStream = -1;
|
vst.vStream = -1;
|
||||||
vst.aStream = -1;
|
vst.aStream = -1;
|
||||||
|
|
||||||
@ -108,7 +102,6 @@ int main( int argc, char *argv[])
|
|||||||
vst.aStream < 0)
|
vst.aStream < 0)
|
||||||
{
|
{
|
||||||
vst.aStream = i;
|
vst.aStream = i;
|
||||||
vst.audio_time_base = vst.fCtx->streams[i]->time_base;
|
|
||||||
if(stream_duration == 0)
|
if(stream_duration == 0)
|
||||||
stream_duration = vst.fCtx->streams[i]->duration;
|
stream_duration = vst.fCtx->streams[i]->duration;
|
||||||
}
|
}
|
||||||
@ -122,12 +115,6 @@ int main( int argc, char *argv[])
|
|||||||
|
|
||||||
// __asm__ __volatile__("int3");
|
// __asm__ __volatile__("int3");
|
||||||
|
|
||||||
// Get a pointer to the codec context for the video stream
|
|
||||||
vst.vCtx = vst.fCtx->streams[vst.vStream]->codec;
|
|
||||||
vst.aCtx = vst.fCtx->streams[vst.aStream]->codec;
|
|
||||||
|
|
||||||
vst.vCodec = avcodec_find_decoder(vst.vCtx->codec_id);
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&vst.input_list);
|
INIT_LIST_HEAD(&vst.input_list);
|
||||||
INIT_LIST_HEAD(&vst.output_list);
|
INIT_LIST_HEAD(&vst.output_list);
|
||||||
mutex_init(&vst.q_video.lock);
|
mutex_init(&vst.q_video.lock);
|
||||||
@ -137,37 +124,14 @@ int main( int argc, char *argv[])
|
|||||||
mutex_init(&vst.input_lock);
|
mutex_init(&vst.input_lock);
|
||||||
mutex_init(&vst.output_lock);
|
mutex_init(&vst.output_lock);
|
||||||
|
|
||||||
if(vst.vCodec == NULL)
|
vst.vCtx = vst.fCtx->streams[vst.vStream]->codec;
|
||||||
{
|
vst.aCtx = vst.fCtx->streams[vst.aStream]->codec;
|
||||||
printf("Unsupported codec with id %d for input stream %d\n",
|
|
||||||
vst.vCtx->codec_id, vst.vStream);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vst.Frame = av_frame_alloc();
|
if(init_video_decoder(&vst) != 0 )
|
||||||
if(vst.Frame == NULL)
|
|
||||||
{
|
|
||||||
printf("Cannot alloc video frame\n");
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(fplay_init_context(&vst))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(avcodec_open2(vst.vCtx, vst.vCodec, NULL) < 0)
|
vst.aCtx->request_channel_layout = AV_CH_LAYOUT_STEREO;
|
||||||
{
|
|
||||||
printf("Error while opening codec for input stream %d\n",
|
|
||||||
vst.vStream);
|
|
||||||
return -1; // Could not open codec
|
|
||||||
};
|
|
||||||
|
|
||||||
if (vst.aCtx->channels > 0)
|
|
||||||
vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels);
|
|
||||||
else
|
|
||||||
vst.aCtx->request_channels = 2;
|
|
||||||
|
|
||||||
vst.aCodec = avcodec_find_decoder(vst.aCtx->codec_id);
|
vst.aCodec = avcodec_find_decoder(vst.aCtx->codec_id);
|
||||||
|
|
||||||
if(vst.aCodec)
|
if(vst.aCodec)
|
||||||
{
|
{
|
||||||
if(avcodec_open2(vst.aCtx, vst.aCodec, NULL) >= 0 )
|
if(avcodec_open2(vst.aCtx, vst.aCodec, NULL) >= 0 )
|
||||||
@ -198,11 +162,11 @@ int main( int argc, char *argv[])
|
|||||||
astream.count = 0;
|
astream.count = 0;
|
||||||
astream.buffer = (char *)av_mallocz(192000*3);
|
astream.buffer = (char *)av_mallocz(192000*3);
|
||||||
if( astream.buffer != NULL )
|
if( astream.buffer != NULL )
|
||||||
have_sound = 1;
|
vst.has_sound = 1;
|
||||||
else
|
else
|
||||||
av_free(decoder_buffer);
|
av_free(decoder_buffer);
|
||||||
}
|
}
|
||||||
if( have_sound == 0)
|
if( vst.has_sound == 0)
|
||||||
{
|
{
|
||||||
printf("Not enough memory for audio buffers\n");
|
printf("Not enough memory for audio buffers\n");
|
||||||
}
|
}
|
||||||
@ -229,9 +193,11 @@ int main( int argc, char *argv[])
|
|||||||
if(astream.lock.handle)
|
if(astream.lock.handle)
|
||||||
mutex_destroy(&astream.lock);
|
mutex_destroy(&astream.lock);
|
||||||
|
|
||||||
|
fini_video_decoder(&vst);
|
||||||
mutex_destroy(&vst.q_video.lock);
|
mutex_destroy(&vst.q_video.lock);
|
||||||
mutex_destroy(&vst.q_audio.lock);
|
mutex_destroy(&vst.q_audio.lock);
|
||||||
mutex_destroy(&vst.decoder_lock);
|
mutex_destroy(&vst.decoder_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,14 +213,14 @@ static int load_frame(vst_t *vst)
|
|||||||
if(packet.stream_index == vst->vStream)
|
if(packet.stream_index == vst->vStream)
|
||||||
put_packet(&vst->q_video, &packet);
|
put_packet(&vst->q_video, &packet);
|
||||||
else if( (packet.stream_index == vst->aStream) &&
|
else if( (packet.stream_index == vst->aStream) &&
|
||||||
(have_sound != 0) )
|
(vst->has_sound != 0) )
|
||||||
{
|
{
|
||||||
put_packet(&vst->q_audio, &packet);
|
put_packet(&vst->q_audio, &packet);
|
||||||
if(audio_base == -1.0)
|
if(vst->audio_timer_valid == 0 &&
|
||||||
|
packet.pts != AV_NOPTS_VALUE )
|
||||||
{
|
{
|
||||||
if (packet.pts != AV_NOPTS_VALUE)
|
vst->audio_timer_base = get_audio_base(vst) * packet.pts;
|
||||||
audio_base = get_audio_base(vst) * packet.pts;
|
vst->audio_timer_valid = 1;
|
||||||
// printf("audio base %f\n", audio_base);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else av_free_packet(&packet);
|
else av_free_packet(&packet);
|
||||||
|
@ -110,6 +110,22 @@ typedef struct {
|
|||||||
int put_packet(queue_t *q, AVPacket *pkt);
|
int put_packet(queue_t *q, AVPacket *pkt);
|
||||||
int get_packet(queue_t *q, AVPacket *pkt);
|
int get_packet(queue_t *q, AVPacket *pkt);
|
||||||
|
|
||||||
|
struct decoder
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
enum AVCodecID codec_id;
|
||||||
|
enum AVPixelFormat pix_fmt;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
AVFrame *Frame;
|
||||||
|
vframe_t *active_frame;
|
||||||
|
void *hwctx;
|
||||||
|
int is_hw:1;
|
||||||
|
int frame_reorder:1;
|
||||||
|
int nframes;
|
||||||
|
vframe_t vframes[16];
|
||||||
|
};
|
||||||
|
|
||||||
struct vstate
|
struct vstate
|
||||||
{
|
{
|
||||||
AVFormatContext *fCtx; /* format context */
|
AVFormatContext *fCtx; /* format context */
|
||||||
@ -122,7 +138,7 @@ struct vstate
|
|||||||
int vStream; /* video stream index */
|
int vStream; /* video stream index */
|
||||||
int aStream; /* audio stream index */
|
int aStream; /* audio stream index */
|
||||||
AVRational video_time_base;
|
AVRational video_time_base;
|
||||||
AVRational audio_time_base;
|
double audio_timer_base;
|
||||||
|
|
||||||
queue_t q_video; /* video packets queue */
|
queue_t q_video; /* video packets queue */
|
||||||
queue_t q_audio; /* audio packets queue */
|
queue_t q_audio; /* audio packets queue */
|
||||||
@ -135,18 +151,13 @@ struct vstate
|
|||||||
struct list_head input_list;
|
struct list_head input_list;
|
||||||
struct list_head output_list;
|
struct list_head output_list;
|
||||||
|
|
||||||
AVFrame *Frame;
|
struct decoder *decoder;
|
||||||
|
|
||||||
vframe_t *decoder_frame;
|
|
||||||
volatile int frames_count;
|
volatile int frames_count;
|
||||||
void *hwCtx; /* hardware context */
|
int has_sound:1;
|
||||||
int hwdec:1; /* hardware decoder */
|
int audio_timer_valid:1;
|
||||||
int blit_bitmap:1; /* hardware RGBA blitter */
|
int blit_bitmap:1; /* hardware RGBA blitter */
|
||||||
int blit_texture:1; /* hardware RGBA blit and scale */
|
int blit_texture:1; /* hardware RGBA blit and scale */
|
||||||
int blit_planar:1; /* hardbare YUV blit and scale */
|
int blit_planar:1; /* hardbare YUV blit and scale */
|
||||||
int frame_reorder:1;
|
|
||||||
int nframes;
|
|
||||||
vframe_t vframes[16];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -173,6 +184,8 @@ void set_audio_volume(int left, int right);
|
|||||||
int video_thread(void *param);
|
int video_thread(void *param);
|
||||||
void flush_video(vst_t* vst);
|
void flush_video(vst_t* vst);
|
||||||
|
|
||||||
|
int init_video_decoder(vst_t *vst);
|
||||||
|
void fini_video_decoder(vst_t *vst);
|
||||||
void decoder(vst_t *vst);
|
void decoder(vst_t *vst);
|
||||||
int decode_video(vst_t* vst);
|
int decode_video(vst_t* vst);
|
||||||
int decode_audio(AVCodecContext *ctx, queue_t *qa);
|
int decode_audio(AVCodecContext *ctx, queue_t *qa);
|
||||||
@ -191,8 +204,13 @@ static inline double get_audio_base(vst_t* vst)
|
|||||||
return (double)av_q2d(vst->fCtx->streams[vst->aStream]->time_base)*1000;
|
return (double)av_q2d(vst->fCtx->streams[vst->aStream]->time_base)*1000;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct decoder* va_init_decoder(vst_t *vst);
|
||||||
void va_create_planar(vst_t *vst, vframe_t *vframe);
|
void va_create_planar(vst_t *vst, vframe_t *vframe);
|
||||||
|
|
||||||
int init_fontlib();
|
int init_fontlib();
|
||||||
char *get_moviefile();
|
char *get_moviefile();
|
||||||
|
|
||||||
|
#define ENTER() printf("enter %s\n",__FUNCTION__)
|
||||||
|
#define LEAVE() printf("leave %s\n",__FUNCTION__)
|
||||||
|
#define FAIL() printf("fail %s\n",__FUNCTION__)
|
||||||
|
|
||||||
|
@ -160,21 +160,6 @@ static const char *string_of_VAEntrypoint(VAEntrypoint entrypoint)
|
|||||||
return "<unknown>";
|
return "<unknown>";
|
||||||
}
|
}
|
||||||
|
|
||||||
VADisplay va_open_display(void)
|
|
||||||
{
|
|
||||||
VADisplay va_dpy;
|
|
||||||
|
|
||||||
drm_fd = get_service("DISPLAY");
|
|
||||||
if (drm_fd == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
va_dpy = vaGetDisplayDRM(drm_fd);
|
|
||||||
if (va_dpy)
|
|
||||||
return va_dpy;
|
|
||||||
|
|
||||||
drm_fd = 0;
|
|
||||||
return NULL;
|
|
||||||
};
|
|
||||||
|
|
||||||
void *vaapi_init(VADisplay display)
|
void *vaapi_init(VADisplay display)
|
||||||
{
|
{
|
||||||
@ -343,7 +328,7 @@ ENTER();
|
|||||||
|
|
||||||
printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height);
|
printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height);
|
||||||
status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height,
|
status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height,
|
||||||
v_surface_id,vst->nframes,NULL,0);
|
v_surface_id,vst->decoder->nframes,NULL,0);
|
||||||
if (!vaapi_check_status(status, "vaCreateSurfaces()"))
|
if (!vaapi_check_status(status, "vaCreateSurfaces()"))
|
||||||
{
|
{
|
||||||
FAIL();
|
FAIL();
|
||||||
@ -378,7 +363,7 @@ ENTER();
|
|||||||
status = vaCreateContext(vaapi->display, config_id,
|
status = vaCreateContext(vaapi->display, config_id,
|
||||||
picture_width, picture_height,
|
picture_width, picture_height,
|
||||||
VA_PROGRESSIVE,
|
VA_PROGRESSIVE,
|
||||||
v_surface_id, vst->nframes,
|
v_surface_id, vst->decoder->nframes,
|
||||||
&context_id);
|
&context_id);
|
||||||
if (!vaapi_check_status(status, "vaCreateContext()"))
|
if (!vaapi_check_status(status, "vaCreateContext()"))
|
||||||
{
|
{
|
||||||
@ -399,7 +384,7 @@ static enum PixelFormat get_format(struct AVCodecContext *avctx,
|
|||||||
vst_t *vst = (vst_t*)avctx->opaque;
|
vst_t *vst = (vst_t*)avctx->opaque;
|
||||||
VAProfile profile = VAProfileNone;
|
VAProfile profile = VAProfileNone;
|
||||||
|
|
||||||
|
ENTER();
|
||||||
for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
|
for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
|
||||||
{
|
{
|
||||||
enum AVCodecID codec = avctx->codec_id;
|
enum AVCodecID codec = avctx->codec_id;
|
||||||
@ -449,7 +434,7 @@ static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
|
|||||||
vst_t *vst = (vst_t*)avctx->opaque;
|
vst_t *vst = (vst_t*)avctx->opaque;
|
||||||
void *surface;
|
void *surface;
|
||||||
|
|
||||||
surface = (void *)(uintptr_t)v_surface_id[vst->decoder_frame->index];
|
surface = (void *)(uintptr_t)v_surface_id[vst->decoder->active_frame->index];
|
||||||
|
|
||||||
pic->data[3] = surface;
|
pic->data[3] = surface;
|
||||||
|
|
||||||
@ -466,71 +451,6 @@ static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
|
|||||||
|
|
||||||
struct vaapi_context va_context_storage;
|
struct vaapi_context va_context_storage;
|
||||||
|
|
||||||
int fplay_init_context(vst_t *vst)
|
|
||||||
{
|
|
||||||
AVCodecContext *vCtx = vst->vCtx;
|
|
||||||
|
|
||||||
vst->nframes = 4;
|
|
||||||
|
|
||||||
if(va_check_codec_support(vCtx->codec_id))
|
|
||||||
{
|
|
||||||
VADisplay dpy;
|
|
||||||
|
|
||||||
dpy = va_open_display();
|
|
||||||
vst->hwCtx = vaapi_init(dpy);
|
|
||||||
|
|
||||||
if(vst->hwCtx != NULL)
|
|
||||||
{
|
|
||||||
if(vCtx->codec_id == AV_CODEC_ID_H264)
|
|
||||||
vst->nframes = 16;
|
|
||||||
|
|
||||||
for(int i = 0; i < vst->nframes; i++)
|
|
||||||
{
|
|
||||||
vframe_t *vframe = &vst->vframes[i];
|
|
||||||
|
|
||||||
vframe->format = AV_PIX_FMT_NONE;
|
|
||||||
vframe->is_hw_pic = 1;
|
|
||||||
vframe->index = i;
|
|
||||||
vframe->pts = 0;
|
|
||||||
vframe->ready = 0;
|
|
||||||
list_add_tail(&vframe->list, &vst->input_list);
|
|
||||||
};
|
|
||||||
|
|
||||||
vst->hwdec = 1;
|
|
||||||
vst->frame_reorder = 1;
|
|
||||||
vCtx->opaque = vst;
|
|
||||||
vCtx->thread_count = 1;
|
|
||||||
vCtx->get_format = get_format;
|
|
||||||
vCtx->get_buffer2 = get_buffer2;
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
vst->hwdec = 0;
|
|
||||||
|
|
||||||
for(int i = 0; i < vst->nframes; i++)
|
|
||||||
{
|
|
||||||
vframe_t *vframe;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
vframe = &vst->vframes[i];
|
|
||||||
|
|
||||||
ret = avpicture_alloc(&vframe->picture, vst->vCtx->pix_fmt,
|
|
||||||
vst->vCtx->width, vst->vCtx->height);
|
|
||||||
if ( ret != 0 )
|
|
||||||
{
|
|
||||||
printf("Cannot alloc video buffer\n\r");
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
vframe->format = vst->vCtx->pix_fmt;
|
|
||||||
vframe->index = i;
|
|
||||||
vframe->pts = 0;
|
|
||||||
vframe->ready = 0;
|
|
||||||
list_add_tail(&vframe->list, &vst->input_list);
|
|
||||||
};
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define EGL_TEXTURE_Y_U_V_WL 0x31D7
|
#define EGL_TEXTURE_Y_U_V_WL 0x31D7
|
||||||
@ -648,7 +568,6 @@ void va_create_planar(vst_t *vst, vframe_t *vframe)
|
|||||||
vaimage.offsets[2],vaimage.pitches[2]);
|
vaimage.offsets[2],vaimage.pitches[2]);
|
||||||
if(planar != NULL)
|
if(planar != NULL)
|
||||||
{
|
{
|
||||||
printf("create planar image\n",planar);
|
|
||||||
vframe->planar = planar;
|
vframe->planar = planar;
|
||||||
vframe->format = AV_PIX_FMT_NV12;
|
vframe->format = AV_PIX_FMT_NV12;
|
||||||
};
|
};
|
||||||
@ -657,3 +576,78 @@ void va_create_planar(vst_t *vst, vframe_t *vframe)
|
|||||||
vaDestroyImage(vaapi->display, vaimage.image_id);
|
vaDestroyImage(vaapi->display, vaimage.image_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct decoder* va_init_decoder(vst_t *vst)
|
||||||
|
{
|
||||||
|
AVCodecContext *vCtx = vst->vCtx;
|
||||||
|
struct decoder *decoder;
|
||||||
|
VADisplay dpy;
|
||||||
|
|
||||||
|
drm_fd = get_service("DISPLAY");
|
||||||
|
if (drm_fd == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dpy = vaGetDisplayDRM(drm_fd);
|
||||||
|
if (dpy == NULL)
|
||||||
|
goto err_0;
|
||||||
|
|
||||||
|
decoder = calloc(1, sizeof(struct decoder));
|
||||||
|
if(decoder == NULL)
|
||||||
|
goto err_0;
|
||||||
|
|
||||||
|
decoder->hwctx = vaapi_init(dpy);
|
||||||
|
if(decoder->hwctx == NULL)
|
||||||
|
goto err_1;
|
||||||
|
|
||||||
|
decoder->Frame = av_frame_alloc();
|
||||||
|
if(decoder->Frame == NULL)
|
||||||
|
goto err_1;
|
||||||
|
|
||||||
|
if(vCtx->codec_id == AV_CODEC_ID_H264)
|
||||||
|
decoder->nframes = 16;
|
||||||
|
else
|
||||||
|
decoder->nframes = 4;
|
||||||
|
|
||||||
|
for(int i = 0; i < decoder->nframes; i++)
|
||||||
|
{
|
||||||
|
vframe_t *vframe = &decoder->vframes[i];
|
||||||
|
|
||||||
|
vframe->format = AV_PIX_FMT_NONE;
|
||||||
|
vframe->is_hw_pic = 1;
|
||||||
|
vframe->index = i;
|
||||||
|
vframe->pts = 0;
|
||||||
|
vframe->ready = 0;
|
||||||
|
list_add_tail(&vframe->list, &vst->input_list);
|
||||||
|
};
|
||||||
|
|
||||||
|
vCtx->opaque = vst;
|
||||||
|
vCtx->thread_count = 1;
|
||||||
|
vCtx->get_format = get_format;
|
||||||
|
vCtx->get_buffer2 = get_buffer2;
|
||||||
|
|
||||||
|
if(avcodec_open2(vst->vCtx, vst->vCodec, NULL) < 0)
|
||||||
|
{
|
||||||
|
printf("Error while opening codec for input stream %d\n",
|
||||||
|
vst->vStream);
|
||||||
|
goto err_2;
|
||||||
|
};
|
||||||
|
|
||||||
|
decoder->name = vst->vCodec->name;
|
||||||
|
decoder->codec_id = vCtx->codec_id;
|
||||||
|
decoder->pix_fmt = vCtx->pix_fmt;
|
||||||
|
decoder->width = vCtx->width;
|
||||||
|
decoder->height = vCtx->height;
|
||||||
|
decoder->is_hw = 1;
|
||||||
|
decoder->frame_reorder = 1;
|
||||||
|
|
||||||
|
return decoder;
|
||||||
|
|
||||||
|
err_2:
|
||||||
|
av_frame_free(&decoder->Frame);
|
||||||
|
err_1:
|
||||||
|
free(decoder);
|
||||||
|
vaTerminate(dpy);
|
||||||
|
err_0:
|
||||||
|
drm_fd = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -40,7 +40,7 @@ void flush_video(vst_t *vst)
|
|||||||
list_for_each_entry_safe(vframe, tmp, &vst->output_list, list)
|
list_for_each_entry_safe(vframe, tmp, &vst->output_list, list)
|
||||||
list_move_tail(&vframe->list, &vst->input_list);
|
list_move_tail(&vframe->list, &vst->input_list);
|
||||||
|
|
||||||
list_for_each_entry(vframe, &vst->output_list, list)
|
list_for_each_entry(vframe, &vst->input_list, list)
|
||||||
{
|
{
|
||||||
vframe->pts = 0;
|
vframe->pts = 0;
|
||||||
vframe->ready = 0;
|
vframe->ready = 0;
|
||||||
@ -52,112 +52,6 @@ void flush_video(vst_t *vst)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static vframe_t *get_input_frame(vst_t *vst)
|
|
||||||
{
|
|
||||||
vframe_t *vframe = NULL;
|
|
||||||
|
|
||||||
mutex_lock(&vst->input_lock);
|
|
||||||
if(!list_empty(&vst->input_list))
|
|
||||||
{
|
|
||||||
vframe = list_first_entry(&vst->input_list, vframe_t, list);
|
|
||||||
list_del(&vframe->list);
|
|
||||||
}
|
|
||||||
mutex_unlock(&vst->input_lock);
|
|
||||||
|
|
||||||
return vframe;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void put_output_frame(vst_t *vst, vframe_t *vframe)
|
|
||||||
{
|
|
||||||
mutex_lock(&vst->output_lock);
|
|
||||||
if(list_empty(&vst->output_list))
|
|
||||||
list_add_tail(&vframe->list, &vst->output_list);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vframe_t *cur;
|
|
||||||
|
|
||||||
cur = list_first_entry(&vst->output_list,vframe_t,list);
|
|
||||||
if(vframe->pts < cur->pts)
|
|
||||||
list_add_tail(&vframe->list, &vst->output_list);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
list_for_each_entry_reverse(cur,&vst->output_list,list)
|
|
||||||
{
|
|
||||||
if(vframe->pts > cur->pts)
|
|
||||||
{
|
|
||||||
list_add(&vframe->list, &cur->list);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
vst->frames_count++;
|
|
||||||
mutex_unlock(&vst->output_lock);
|
|
||||||
};
|
|
||||||
|
|
||||||
int decode_video(vst_t* vst)
|
|
||||||
{
|
|
||||||
double pts;
|
|
||||||
AVPacket pkt;
|
|
||||||
|
|
||||||
int frameFinished;
|
|
||||||
|
|
||||||
if(vst->decoder_frame == NULL)
|
|
||||||
vst->decoder_frame = get_input_frame(vst);
|
|
||||||
|
|
||||||
if(vst->decoder_frame == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if( get_packet(&vst->q_video, &pkt) == 0 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
frameFinished = 0;
|
|
||||||
|
|
||||||
mutex_lock(&vst->gpu_lock);
|
|
||||||
|
|
||||||
if(avcodec_decode_video2(vst->vCtx, vst->Frame, &frameFinished, &pkt) <= 0)
|
|
||||||
printf("video decoder error\n");
|
|
||||||
|
|
||||||
if(frameFinished)
|
|
||||||
{
|
|
||||||
vframe_t *vframe = vst->decoder_frame;;
|
|
||||||
AVPicture *dst_pic;
|
|
||||||
|
|
||||||
if(vst->hwdec)
|
|
||||||
pts = pkt.pts;
|
|
||||||
else
|
|
||||||
pts = av_frame_get_best_effort_timestamp(vst->Frame);
|
|
||||||
|
|
||||||
pts*= av_q2d(vst->video_time_base);
|
|
||||||
|
|
||||||
dst_pic = &vframe->picture;
|
|
||||||
|
|
||||||
if(vframe->is_hw_pic == 0)
|
|
||||||
av_image_copy(dst_pic->data, dst_pic->linesize,
|
|
||||||
(const uint8_t**)vst->Frame->data,
|
|
||||||
vst->Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height);
|
|
||||||
else
|
|
||||||
va_create_planar(vst, vframe);
|
|
||||||
|
|
||||||
vframe->pts = pts*1000.0;
|
|
||||||
vframe->pkt_pts = pkt.pts*av_q2d(vst->video_time_base)*1000.0;
|
|
||||||
vframe->ready = 1;
|
|
||||||
|
|
||||||
put_output_frame(vst, vframe);
|
|
||||||
|
|
||||||
// printf("decoded index: %d pts: %f pkt_pts %f pkt_dts %f\n",
|
|
||||||
// vst->dfx, vst->vframe[vst->dfx].pts,
|
|
||||||
// vst->vframe[vst->dfx].pkt_pts, vst->vframe[vst->dfx].pkt_dts);
|
|
||||||
|
|
||||||
vst->decoder_frame = NULL;
|
|
||||||
};
|
|
||||||
av_frame_unref(vst->Frame);
|
|
||||||
mutex_unlock(&vst->gpu_lock);
|
|
||||||
|
|
||||||
av_free_packet(&pkt);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern volatile enum player_state player_state;
|
extern volatile enum player_state player_state;
|
||||||
extern volatile enum player_state decoder_state;
|
extern volatile enum player_state decoder_state;
|
||||||
@ -482,6 +376,18 @@ int video_thread(void *param)
|
|||||||
|
|
||||||
__sync_and_and_fetch(&threads_running,~VIDEO_THREAD);
|
__sync_and_and_fetch(&threads_running,~VIDEO_THREAD);
|
||||||
|
|
||||||
|
{
|
||||||
|
vframe_t *vframe, *tmp;
|
||||||
|
flush_video(vst);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(vframe, tmp, &vst->output_list, list)
|
||||||
|
{
|
||||||
|
list_del(&vframe->list);
|
||||||
|
if(vframe->planar != NULL)
|
||||||
|
pxDestroyPlanar(vframe->planar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
destroy_render(main_render);
|
destroy_render(main_render);
|
||||||
fini_winlib();
|
fini_winlib();
|
||||||
player_state = CLOSED;
|
player_state = CLOSED;
|
||||||
@ -737,7 +643,6 @@ static void render_hw_planar(render_t *render, vframe_t *vframe)
|
|||||||
CAPTION_HEIGHT+render->rcvideo.t,
|
CAPTION_HEIGHT+render->rcvideo.t,
|
||||||
render->rcvideo.r, render->rcvideo.b,0,0);
|
render->rcvideo.r, render->rcvideo.b,0,0);
|
||||||
mutex_unlock(&render->vst->gpu_lock);
|
mutex_unlock(&render->vst->gpu_lock);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -770,7 +675,7 @@ void draw_hw_picture(render_t *render, vframe_t *vframe)
|
|||||||
dst_height = render->rcvideo.b;
|
dst_height = render->rcvideo.b;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(vst->hwdec)
|
if(vframe->is_hw_pic)
|
||||||
{
|
{
|
||||||
render_hw_planar(render, vframe);
|
render_hw_planar(render, vframe);
|
||||||
return;
|
return;
|
||||||
@ -778,7 +683,7 @@ void draw_hw_picture(render_t *render, vframe_t *vframe)
|
|||||||
|
|
||||||
picture = &vframe->picture;
|
picture = &vframe->picture;
|
||||||
|
|
||||||
format = render->vst->hwdec == 0 ? render->ctx_format : AV_PIX_FMT_BGRA;
|
format = render->ctx_format;
|
||||||
cvt_ctx = sws_getCachedContext(cvt_ctx, render->ctx_width, render->ctx_height, format,
|
cvt_ctx = sws_getCachedContext(cvt_ctx, render->ctx_width, render->ctx_height, format,
|
||||||
dst_width, dst_height, AV_PIX_FMT_BGRA,
|
dst_width, dst_height, AV_PIX_FMT_BGRA,
|
||||||
SWS_FAST_BILINEAR, NULL, NULL, NULL);
|
SWS_FAST_BILINEAR, NULL, NULL, NULL);
|
||||||
|
@ -16,6 +16,7 @@ uint32_t main_cursor;
|
|||||||
|
|
||||||
static int button_proc(ctrl_t *btn, uint32_t msg, uint32_t arg1, uint32_t arg2);
|
static int button_proc(ctrl_t *btn, uint32_t msg, uint32_t arg1, uint32_t arg2);
|
||||||
static int spinbtn_proc(ctrl_t *btn, uint32_t msg, uint32_t arg1, uint32_t arg2);
|
static int spinbtn_proc(ctrl_t *btn, uint32_t msg, uint32_t arg1, uint32_t arg2);
|
||||||
|
void panel_set_layout(ctrl_t *panel, int layout);
|
||||||
|
|
||||||
ctrl_t *create_control(size_t size, int id, int x, int y,
|
ctrl_t *create_control(size_t size, int id, int x, int y,
|
||||||
int w, int h, ctrl_t *parent)
|
int w, int h, ctrl_t *parent)
|
||||||
|
@ -25,6 +25,8 @@ extern int res_full_btn_pressed[];
|
|||||||
extern uint32_t main_cursor;
|
extern uint32_t main_cursor;
|
||||||
|
|
||||||
void update_caption_size(window_t *win);
|
void update_caption_size(window_t *win);
|
||||||
|
void window_update_layout(window_t *win);
|
||||||
|
int draw_text_ext(void *pixmap, uint32_t pitch, int face, char *text, rect_t *rc, int color);
|
||||||
|
|
||||||
int caption_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2);
|
int caption_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2);
|
||||||
|
|
||||||
|
@ -203,6 +203,7 @@ static inline int pt_in_rect(rect_t *rc, int x, int y)
|
|||||||
ctrl_t *get_child(ctrl_t *ctrl, int x, int y);
|
ctrl_t *get_child(ctrl_t *ctrl, int x, int y);
|
||||||
|
|
||||||
ctrl_t *capture_mouse(ctrl_t *newm);
|
ctrl_t *capture_mouse(ctrl_t *newm);
|
||||||
|
void release_mouse(void);
|
||||||
|
|
||||||
void blit_raw(ctx_t *ctx, void *raw, int x, int y, int w, int h, int pitch);
|
void blit_raw(ctx_t *ctx, void *raw, int x, int y, int w, int h, int pitch);
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ void adjust_frame(window_t *win);
|
|||||||
void blit_panel(panel_t *panel);
|
void blit_panel(panel_t *panel);
|
||||||
void update_panel_size(window_t *win);
|
void update_panel_size(window_t *win);
|
||||||
void update_caption_size(window_t *win);
|
void update_caption_size(window_t *win);
|
||||||
|
int init_fontlib();
|
||||||
|
|
||||||
//#include "timer.h"
|
//#include "timer.h"
|
||||||
ctrl_t *win_get_child(window_t *win, int x, int y)
|
ctrl_t *win_get_child(window_t *win, int x, int y)
|
||||||
|
Loading…
Reference in New Issue
Block a user