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
|
||||
|
||||
FASM= fasm.exe
|
||||
@ -27,6 +26,7 @@ LDFLAGS = -static -nostdlib --stack 0x200000 -Map fplay.map -T$(SDK_DIR)/sources
|
||||
|
||||
SOURCES = opendial.asm \
|
||||
audio.c \
|
||||
decoder.c \
|
||||
fplay.c \
|
||||
vaapi.c \
|
||||
video.c \
|
||||
|
@ -29,9 +29,6 @@ static int snd_format;
|
||||
int sample_rate;
|
||||
|
||||
static uint32_t samples_written = 0;
|
||||
double audio_base = -1.0;
|
||||
|
||||
double get_audio_base();
|
||||
|
||||
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,
|
||||
aFrame->nb_samples,
|
||||
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.size -= len;
|
||||
|
||||
@ -254,6 +243,7 @@ static void sync_audio(SNDBUF hbuff, int buffsize)
|
||||
|
||||
int audio_thread(void *param)
|
||||
{
|
||||
vst_t *vst = param;
|
||||
SND_EVENT evnt;
|
||||
|
||||
int buffsize;
|
||||
@ -306,11 +296,10 @@ int audio_thread(void *param)
|
||||
memcpy(astream.buffer, astream.buffer+buffsize*2, astream.count);
|
||||
mutex_unlock(&astream.lock);
|
||||
|
||||
SetTimeBase(hBuff, audio_base);
|
||||
SetTimeBase(hBuff, vst->audio_timer_base);
|
||||
|
||||
case PAUSE_2_PLAY:
|
||||
GetTimeStamp(hBuff, &last_time_stamp);
|
||||
// printf("last audio time stamp %f\n", last_time_stamp);
|
||||
|
||||
if((err = PlayBuffer(hBuff, 0)) !=0 )
|
||||
{
|
||||
@ -320,7 +309,6 @@ int audio_thread(void *param)
|
||||
active = 1;
|
||||
sync_audio(hBuff, buffsize);
|
||||
sound_state = PLAY;
|
||||
// printf("render: set audio latency to %f\n", audio_delta);
|
||||
|
||||
/* breaktrough */
|
||||
|
||||
@ -385,7 +373,7 @@ int audio_thread(void *param)
|
||||
if( active )
|
||||
{
|
||||
ResetBuffer(hBuff, SND_RESET_ALL);
|
||||
audio_base = -1.0;
|
||||
vst->audio_timer_valid = 0;
|
||||
active = 0;
|
||||
}
|
||||
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;
|
||||
|
||||
int have_sound = 0;
|
||||
|
||||
uint8_t *decoder_buffer;
|
||||
extern int resampler_size;
|
||||
extern int sample_rate;
|
||||
@ -34,8 +32,6 @@ int64_t stream_duration;
|
||||
|
||||
int threads_running = DECODER_THREAD;
|
||||
|
||||
extern double audio_base;
|
||||
|
||||
|
||||
int main( int argc, char *argv[])
|
||||
{
|
||||
@ -70,7 +66,6 @@ int main( int argc, char *argv[])
|
||||
|
||||
vst.fCtx->flags |= AVFMT_FLAG_GENPTS;
|
||||
|
||||
// Retrieve stream information
|
||||
if(avformat_find_stream_info(vst.fCtx, NULL) < 0)
|
||||
{
|
||||
printf("Cannot find streams\n\r");
|
||||
@ -89,7 +84,6 @@ int main( int argc, char *argv[])
|
||||
|
||||
stream_duration = vst.fCtx->duration;
|
||||
|
||||
// Find the first video stream
|
||||
vst.vStream = -1;
|
||||
vst.aStream = -1;
|
||||
|
||||
@ -108,7 +102,6 @@ int main( int argc, char *argv[])
|
||||
vst.aStream < 0)
|
||||
{
|
||||
vst.aStream = i;
|
||||
vst.audio_time_base = vst.fCtx->streams[i]->time_base;
|
||||
if(stream_duration == 0)
|
||||
stream_duration = vst.fCtx->streams[i]->duration;
|
||||
}
|
||||
@ -122,12 +115,6 @@ int main( int argc, char *argv[])
|
||||
|
||||
// __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.output_list);
|
||||
mutex_init(&vst.q_video.lock);
|
||||
@ -137,37 +124,14 @@ int main( int argc, char *argv[])
|
||||
mutex_init(&vst.input_lock);
|
||||
mutex_init(&vst.output_lock);
|
||||
|
||||
if(vst.vCodec == NULL)
|
||||
{
|
||||
printf("Unsupported codec with id %d for input stream %d\n",
|
||||
vst.vCtx->codec_id, vst.vStream);
|
||||
return -1;
|
||||
}
|
||||
vst.vCtx = vst.fCtx->streams[vst.vStream]->codec;
|
||||
vst.aCtx = vst.fCtx->streams[vst.aStream]->codec;
|
||||
|
||||
vst.Frame = av_frame_alloc();
|
||||
if(vst.Frame == NULL)
|
||||
{
|
||||
printf("Cannot alloc video frame\n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(fplay_init_context(&vst))
|
||||
if(init_video_decoder(&vst) != 0 )
|
||||
return -1;
|
||||
|
||||
if(avcodec_open2(vst.vCtx, vst.vCodec, NULL) < 0)
|
||||
{
|
||||
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.aCtx->request_channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
vst.aCodec = avcodec_find_decoder(vst.aCtx->codec_id);
|
||||
|
||||
if(vst.aCodec)
|
||||
{
|
||||
if(avcodec_open2(vst.aCtx, vst.aCodec, NULL) >= 0 )
|
||||
@ -198,11 +162,11 @@ int main( int argc, char *argv[])
|
||||
astream.count = 0;
|
||||
astream.buffer = (char *)av_mallocz(192000*3);
|
||||
if( astream.buffer != NULL )
|
||||
have_sound = 1;
|
||||
vst.has_sound = 1;
|
||||
else
|
||||
av_free(decoder_buffer);
|
||||
}
|
||||
if( have_sound == 0)
|
||||
if( vst.has_sound == 0)
|
||||
{
|
||||
printf("Not enough memory for audio buffers\n");
|
||||
}
|
||||
@ -229,9 +193,11 @@ int main( int argc, char *argv[])
|
||||
if(astream.lock.handle)
|
||||
mutex_destroy(&astream.lock);
|
||||
|
||||
fini_video_decoder(&vst);
|
||||
mutex_destroy(&vst.q_video.lock);
|
||||
mutex_destroy(&vst.q_audio.lock);
|
||||
mutex_destroy(&vst.decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -247,14 +213,14 @@ static int load_frame(vst_t *vst)
|
||||
if(packet.stream_index == vst->vStream)
|
||||
put_packet(&vst->q_video, &packet);
|
||||
else if( (packet.stream_index == vst->aStream) &&
|
||||
(have_sound != 0) )
|
||||
(vst->has_sound != 0) )
|
||||
{
|
||||
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)
|
||||
audio_base = get_audio_base(vst) * packet.pts;
|
||||
// printf("audio base %f\n", audio_base);
|
||||
vst->audio_timer_base = get_audio_base(vst) * packet.pts;
|
||||
vst->audio_timer_valid = 1;
|
||||
};
|
||||
}
|
||||
else av_free_packet(&packet);
|
||||
|
@ -110,6 +110,22 @@ typedef struct {
|
||||
int put_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
|
||||
{
|
||||
AVFormatContext *fCtx; /* format context */
|
||||
@ -122,7 +138,7 @@ struct vstate
|
||||
int vStream; /* video stream index */
|
||||
int aStream; /* audio stream index */
|
||||
AVRational video_time_base;
|
||||
AVRational audio_time_base;
|
||||
double audio_timer_base;
|
||||
|
||||
queue_t q_video; /* video packets queue */
|
||||
queue_t q_audio; /* audio packets queue */
|
||||
@ -135,18 +151,13 @@ struct vstate
|
||||
struct list_head input_list;
|
||||
struct list_head output_list;
|
||||
|
||||
AVFrame *Frame;
|
||||
|
||||
vframe_t *decoder_frame;
|
||||
struct decoder *decoder;
|
||||
volatile int frames_count;
|
||||
void *hwCtx; /* hardware context */
|
||||
int hwdec:1; /* hardware decoder */
|
||||
int has_sound:1;
|
||||
int audio_timer_valid:1;
|
||||
int blit_bitmap:1; /* hardware RGBA blitter */
|
||||
int blit_texture:1; /* hardware RGBA 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);
|
||||
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);
|
||||
int decode_video(vst_t* vst);
|
||||
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;
|
||||
};
|
||||
|
||||
struct decoder* va_init_decoder(vst_t *vst);
|
||||
void va_create_planar(vst_t *vst, vframe_t *vframe);
|
||||
|
||||
int init_fontlib();
|
||||
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>";
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -343,7 +328,7 @@ ENTER();
|
||||
|
||||
printf("vaCreateSurfaces %dx%d\n",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()"))
|
||||
{
|
||||
FAIL();
|
||||
@ -378,7 +363,7 @@ ENTER();
|
||||
status = vaCreateContext(vaapi->display, config_id,
|
||||
picture_width, picture_height,
|
||||
VA_PROGRESSIVE,
|
||||
v_surface_id, vst->nframes,
|
||||
v_surface_id, vst->decoder->nframes,
|
||||
&context_id);
|
||||
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;
|
||||
VAProfile profile = VAProfileNone;
|
||||
|
||||
|
||||
ENTER();
|
||||
for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
|
||||
@ -466,71 +451,6 @@ static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
|
||||
|
||||
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
|
||||
@ -648,7 +568,6 @@ void va_create_planar(vst_t *vst, vframe_t *vframe)
|
||||
vaimage.offsets[2],vaimage.pitches[2]);
|
||||
if(planar != NULL)
|
||||
{
|
||||
printf("create planar image\n",planar);
|
||||
vframe->planar = planar;
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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_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->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 decoder_state;
|
||||
@ -482,6 +376,18 @@ int video_thread(void *param)
|
||||
|
||||
__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);
|
||||
fini_winlib();
|
||||
player_state = CLOSED;
|
||||
@ -737,7 +643,6 @@ static void render_hw_planar(render_t *render, vframe_t *vframe)
|
||||
CAPTION_HEIGHT+render->rcvideo.t,
|
||||
render->rcvideo.r, render->rcvideo.b,0,0);
|
||||
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;
|
||||
};
|
||||
|
||||
if(vst->hwdec)
|
||||
if(vframe->is_hw_pic)
|
||||
{
|
||||
render_hw_planar(render, vframe);
|
||||
return;
|
||||
@ -778,7 +683,7 @@ void draw_hw_picture(render_t *render, vframe_t *vframe)
|
||||
|
||||
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,
|
||||
dst_width, dst_height, AV_PIX_FMT_BGRA,
|
||||
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 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,
|
||||
int w, int h, ctrl_t *parent)
|
||||
|
@ -25,6 +25,8 @@ extern int res_full_btn_pressed[];
|
||||
extern uint32_t main_cursor;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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 *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);
|
||||
|
||||
|
@ -38,6 +38,7 @@ void adjust_frame(window_t *win);
|
||||
void blit_panel(panel_t *panel);
|
||||
void update_panel_size(window_t *win);
|
||||
void update_caption_size(window_t *win);
|
||||
int init_fontlib();
|
||||
|
||||
//#include "timer.h"
|
||||
ctrl_t *win_get_child(window_t *win, int x, int y)
|
||||
|
Loading…
Reference in New Issue
Block a user