Fplay: new init_decoder()/fini_decoder()

git-svn-id: svn://kolibrios.org@6144 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2016-02-05 19:36:09 +00:00
parent 3a7404eddd
commit 4b978f2310
11 changed files with 375 additions and 267 deletions

View File

@ -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 \

View File

@ -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;

View 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;
}

View File

@ -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);

View File

@ -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__)

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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)