Fplay: update

git-svn-id: svn://kolibrios.org@6658 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2016-11-03 10:00:13 +00:00
parent 587cdc9c87
commit 47d330f439
7 changed files with 179 additions and 113 deletions

View File

@ -16,13 +16,11 @@ LIB_DIR:= $(SDK_DIR)/lib
INCLUDES= -I. -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR)/sources/ffmpeg/ffmpeg-2.8
INCLUDES+=-I$(SDK_DIR)/sources/freetype/include -I$(SDK_DIR)/sources/vaapi/libva-1.6.2
DEFINES= -DDEBUG=1 -DHAVE_VAAPI -DPACKAGE_NAME=\"Fplay-vaapi\"
DEFINES= -DDEBUG=1 -D_GNU_SOURCE -DHAVE_VAAPI -DPACKAGE_NAME=\"Fplay-vaapi\"
LIBS:= -lavdevice.dll -lavformat.dll -lavcodec.dll -lavutil.dll -lswscale.dll
LIBS+= -lswresample.dll -lsound -lpixlib3 -lfreetype.dll -lva.dll -lgcc -lc.dll -lapp
LIBS+= -lswresample.dll -lsound -lpixlib3 -lfreetype.dll -lva.dll -lgcc -lc.dll
LIBPATH:= -L$(LIB_DIR) -L/home/autobuild/tools/win32/mingw32/lib
LDFLAGS = -static -nostdlib --stack 0x200000 -Map fplay.map -T$(SDK_DIR)/sources/newlib/app.lds --image-base 0
LDFLAGS = -static --subsystem native --stack 0x200000 -Map fplay.map -Tapp-dynamic.lds --image-base 0
SOURCES = opendial.asm \
audio.c \
@ -46,7 +44,7 @@ OBJECTS = $(patsubst %.asm, %.o, $(patsubst %.c, %.o, $(SOURCES)))
all:$(NAME)
$(NAME): $(OBJECTS) Makefile
$(LD) $(LDFLAGS) $(LIBPATH) --subsystem native -o $@ $(OBJECTS) $(LIBS)
$(LD) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)
kos32-objcopy $@ -O binary
%.o : %.c Makefile

View File

@ -14,6 +14,27 @@
#include "sound.h"
#include "fplay.h"
static struct decoder ffmpeg_decoder;
static struct decoder* init_ffmpeg_decoder(vst_t *vst);
static decoder_init_fn* decoders[] = {
init_va_decoder,
init_ffmpeg_decoder,
NULL
};
static void fini_ffmpeg_decoder(vst_t *vst)
{
av_frame_free(&vst->decoder->Frame);
for(int i = 0; i < vst->decoder->nframes; i++)
{
vframe_t *vframe;
vframe = &vst->decoder->vframes[i];
avpicture_free(&vframe->picture);
};
};
static struct decoder* init_ffmpeg_decoder(vst_t *vst)
{
AVCodecContext *vCtx = vst->vCtx;
@ -21,9 +42,7 @@ static struct decoder* init_ffmpeg_decoder(vst_t *vst)
vframe_t *vframe;
int i, ret;
decoder = calloc(1, sizeof(struct decoder));
if(decoder == NULL)
return NULL;
decoder = &ffmpeg_decoder;
decoder->Frame = av_frame_alloc();
if(decoder->Frame == NULL)
@ -42,8 +61,6 @@ static struct decoder* init_ffmpeg_decoder(vst_t *vst)
vframe->format = vCtx->pix_fmt;
vframe->index = i;
vframe->pts = 0;
vframe->ready = 0;
list_add_tail(&vframe->list, &vst->input_list);
};
@ -59,7 +76,8 @@ static struct decoder* init_ffmpeg_decoder(vst_t *vst)
decoder->width = vCtx->width;
decoder->height = vCtx->height;
decoder->codec_id = vCtx->codec_id;
decoder->profile = vCtx->profile;
decoder->fini = fini_ffmpeg_decoder;
return decoder;
err_1:
@ -68,60 +86,10 @@ err_1:
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;
@ -230,3 +198,36 @@ int decode_video(vst_t* vst)
return 1;
}
int init_video_decoder(vst_t *vst)
{
decoder_init_fn **init_fn;
AVCodecContext *vCtx = vst->vCtx;
int i;
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;
}
for(init_fn = decoders; init_fn != NULL; init_fn++)
{
vst->decoder = (*init_fn)(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;
}

View File

@ -30,8 +30,7 @@ int64_t rewind_pos;
int64_t stream_duration;
int threads_running = DECODER_THREAD;
volatile int threads_running = DECODER_THREAD;
int main( int argc, char *argv[])
{
@ -113,7 +112,6 @@ int main( int argc, char *argv[])
return -1; // Didn't find a video stream
};
// __asm__ __volatile__("int3");
INIT_LIST_HEAD(&vst.input_list);
INIT_LIST_HEAD(&vst.output_list);
@ -127,6 +125,8 @@ int main( int argc, char *argv[])
vst.vCtx = vst.fCtx->streams[vst.vStream]->codec;
vst.aCtx = vst.fCtx->streams[vst.aStream]->codec;
// __asm__ __volatile__("int3");
if(init_video_decoder(&vst) != 0 )
return -1;
@ -193,7 +193,9 @@ int main( int argc, char *argv[])
if(astream.lock.handle)
mutex_destroy(&astream.lock);
fini_video_decoder(&vst);
vst.decoder->fini(&vst);
avcodec_close(vst.vCtx);
mutex_destroy(&vst.q_video.lock);
mutex_destroy(&vst.q_audio.lock);
mutex_destroy(&vst.decoder_lock);

View File

@ -114,18 +114,23 @@ struct decoder
{
const char *name;
enum AVCodecID codec_id;
int profile;
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];
int nframes;
int is_hw:1;
int has_surfaces:1;
int frame_reorder:1;
void (*fini)(vst_t *vst);
};
typedef struct decoder* decoder_init_fn(vst_t *vst);
struct decoder* init_va_decoder(vst_t *vst);
struct vstate
{
AVFormatContext *fCtx; /* format context */
@ -133,8 +138,6 @@ struct vstate
AVCodecContext *aCtx; /* audio decoder context */
AVCodec *vCodec; /* video codec */
AVCodec *aCodec; /* audio codec */
enum AVCodecID codec_id;
int codec_profile;
char *input_file;
char *input_name;
int vStream; /* video stream index */
@ -152,6 +155,7 @@ struct vstate
mutex_t output_lock;
struct list_head input_list;
struct list_head output_list;
struct list_head destructor_list;
struct decoder *decoder;
int snd_format;
@ -168,7 +172,7 @@ struct vstate
#define AUDIO_THREAD 2
#define VIDEO_THREAD 4
extern int threads_running;
extern volatile int threads_running;
extern astream_t astream;
render_t *create_render(vst_t *vst, window_t *win, uint32_t flags);
@ -217,3 +221,4 @@ char *get_moviefile();
#define LEAVE() printf("leave %s\n",__FUNCTION__)
#define FAIL() printf("fail %s\n",__FUNCTION__)

View File

@ -1,8 +1,9 @@
#include <sys/types.h>
#include <stdint.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include "winlib/winlib.h"

View File

@ -37,11 +37,19 @@ struct hw_profile
#undef ARRAY_ELEMS
#define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
struct va_decoder
{
struct decoder decoder;
VADisplay dpy;
void *hwctx;
VASurfaceID v_surface_id[16];
};
static struct va_decoder va_decoder;
static int drm_fd = 0;
static struct vaapi_context *v_context;
static VASurfaceID v_surface_id[16];
#define HAS_HEVC VA_CHECK_VERSION(0, 38, 0)
#define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0))
@ -281,6 +289,7 @@ static int vaapi_init_decoder(vst_t *vst,VAProfile profile,
unsigned int picture_height)
{
struct vaapi_context* const vaapi = v_context;
struct va_decoder *hw_decoder = (struct va_decoder*)vst->decoder;
VAConfigAttrib attrib;
VAConfigID config_id = VA_INVALID_ID;
VAContextID context_id = VA_INVALID_ID;
@ -309,9 +318,19 @@ ENTER();
return -1;
};
if (vaapi->context_id != VA_INVALID_ID)
vaDestroyContext(vaapi->display, vaapi->context_id);
if (hw_decoder->decoder.has_surfaces)
{
vaDestroySurfaces(vaapi->display,hw_decoder->v_surface_id,hw_decoder->decoder.nframes);
hw_decoder->decoder.has_surfaces = 0;
}
if (vaapi->config_id != VA_INVALID_ID)
vaDestroyConfig(vaapi->display, vaapi->config_id);
attrib.type = VAConfigAttribRTFormat;
printf("vaGetConfigAttributes\n");
@ -341,17 +360,20 @@ 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->decoder->nframes,NULL,0);
hw_decoder->v_surface_id,hw_decoder->decoder.nframes,NULL,0);
if (!vaapi_check_status(status, "vaCreateSurfaces()"))
{
FAIL();
return -1;
};
hw_decoder->decoder.has_surfaces = 1;
{
VAImage vaimage;
VABufferInfo info = {0};
vaDeriveImage(vaapi->display,v_surface_id[0],&vaimage);
vaDeriveImage(vaapi->display,hw_decoder->v_surface_id[0],&vaimage);
printf("vaDeriveImage: %x fourcc: %x\n"
"offset0: %d pitch0: %d\n"
"offset1: %d pitch1: %d\n"
@ -376,7 +398,7 @@ ENTER();
status = vaCreateContext(vaapi->display, config_id,
picture_width, picture_height,
VA_PROGRESSIVE,
v_surface_id, vst->decoder->nframes,
hw_decoder->v_surface_id, vst->decoder->nframes,
&context_id);
if (!vaapi_check_status(status, "vaCreateContext()"))
{
@ -395,24 +417,19 @@ static enum PixelFormat get_format(struct AVCodecContext *avctx,
const enum AVPixelFormat *fmt)
{
vst_t *vst = (vst_t*)avctx->opaque;
struct va_decoder* hw_decoder = (struct va_decoder*)vst->decoder;
struct decoder* decoder = &hw_decoder->decoder;
VAProfile profile = avctx->profile;
enum AVCodecID codec = avctx->codec_id;
if (codec == AV_CODEC_ID_H264)
if(avctx->hwaccel_context != NULL)
{
if(profile == FF_PROFILE_H264_BASELINE)
profile = FF_PROFILE_H264_CONSTRAINED_BASELINE;
};
if(avctx->hwaccel_context != NULL &&
(vst->codec_id != codec ||
vst->codec_profile != profile))
if(decoder->codec_id != avctx->codec_id ||
decoder->profile != avctx->profile)
{
struct decoder* decoder = vst->decoder;
printf("\n%s codec changed!!!\n"
"old id %d profile %x new id %d profile %x\n",
__FUNCTION__, vst->codec_id, vst->codec_profile,
__FUNCTION__, decoder->codec_id, decoder->profile,
codec, profile);
for(int i = 0; i < decoder->nframes; i++)
@ -421,6 +438,15 @@ static enum PixelFormat get_format(struct AVCodecContext *avctx,
vframe->format = AV_PIX_FMT_NONE;
};
}
else
return AV_PIX_FMT_VAAPI_VLD;
}
if (codec == AV_CODEC_ID_H264)
{
if(profile == FF_PROFILE_H264_BASELINE)
profile = FF_PROFILE_H264_CONSTRAINED_BASELINE;
};
printf("\n%s codec %d profile %x\n", __FUNCTION__,avctx->codec_id, avctx->profile);
@ -438,8 +464,6 @@ static enum PixelFormat get_format(struct AVCodecContext *avctx,
if (vaapi_init_decoder(vst, profile, VAEntrypointVLD, avctx->width, avctx->height) == 0)
{
avctx->hwaccel_context = v_context;
vst->codec_id = codec;
vst->codec_profile = profile;
printf("%s format: %x\n",__FUNCTION__, fmt[i]);
return fmt[i];
}
@ -466,9 +490,10 @@ static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
{
static struct av_surface avsurface;
vst_t *vst = (vst_t*)avctx->opaque;
struct va_decoder* hw_decoder = (struct va_decoder*)vst->decoder;
void *surface;
surface = (void *)(uintptr_t)v_surface_id[vst->decoder->active_frame->index];
surface = (void *)(uintptr_t)hw_decoder->v_surface_id[vst->decoder->active_frame->index];
pic->data[3] = surface;
@ -547,18 +572,25 @@ enum wl_drm_format {
void va_create_planar(vst_t *vst, vframe_t *vframe)
{
struct vaapi_context* const vaapi = v_context;
struct va_decoder* hw_decoder = (struct va_decoder*)vst->decoder;
VABufferInfo info = {0};
VAImage vaimage;
VAStatus status;
planar_t *planar;
vaSyncSurface(vaapi->display,v_surface_id[vframe->index]);
vaSyncSurface(vaapi->display,hw_decoder->v_surface_id[vframe->index]);
if(vframe->format != AV_PIX_FMT_NONE)
return;
status = vaDeriveImage(vaapi->display,v_surface_id[vframe->index],&vaimage);
if(vframe->planar != NULL)
{
pxDestroyPlanar(vframe->planar);
vframe->planar = NULL;
};
status = vaDeriveImage(vaapi->display,hw_decoder->v_surface_id[vframe->index],&vaimage);
if (!vaapi_check_status(status, "vaDeriveImage()"))
{
FAIL();
@ -687,29 +719,57 @@ err_0:
return profile;
}
struct decoder* va_init_decoder(vst_t *vst)
static void fini_va_decoder(vst_t *vst)
{
struct vaapi_context* const vaapi = v_context;
struct va_decoder *hw_decoder = (struct va_decoder*)vst->decoder;
ENTER();
for(int i = 0; i < hw_decoder->decoder.nframes; i++)
{
vframe_t *vframe = &hw_decoder->decoder.vframes[i];
if(vframe->planar != NULL)
{
printf("destroy planar %d\n", i);
pxDestroyPlanar(vframe->planar);
vframe->planar = NULL;
};
};
av_frame_free(&hw_decoder->decoder.Frame);
if (vaapi->context_id != VA_INVALID_ID)
vaDestroyContext(vaapi->display, vaapi->context_id);
if (hw_decoder->decoder.has_surfaces)
vaDestroySurfaces(vaapi->display,hw_decoder->v_surface_id,hw_decoder->decoder.nframes);
if (vaapi->config_id != VA_INVALID_ID)
vaDestroyConfig(vaapi->display, vaapi->config_id);
vaTerminate(hw_decoder->dpy);
LEAVE();
};
struct decoder* init_va_decoder(vst_t *vst)
{
AVCodecContext *vCtx = vst->vCtx;
struct decoder *decoder;
VADisplay dpy;
struct va_decoder *hw_decoder = &va_decoder;
struct decoder *decoder = &hw_decoder->decoder;
drm_fd = get_service("DISPLAY");
if (drm_fd == 0)
return NULL;
dpy = vaGetDisplayDRM(drm_fd);
if (dpy == NULL)
hw_decoder->dpy = vaGetDisplayDRM(drm_fd);
if (hw_decoder->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)
hw_decoder->hwctx = vaapi_init(hw_decoder->dpy);
if(hw_decoder->hwctx == NULL)
goto err_1;
if(get_profile(dpy, vCtx->codec_id) == VAProfileNone)
if(get_profile(hw_decoder->dpy, vCtx->codec_id) == VAProfileNone)
goto err_1;
decoder->Frame = av_frame_alloc();
@ -728,8 +788,6 @@ struct decoder* va_init_decoder(vst_t *vst)
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);
};
@ -747,19 +805,20 @@ struct decoder* va_init_decoder(vst_t *vst)
decoder->name = vst->vCodec->name;
decoder->codec_id = vCtx->codec_id;
decoder->profile = vCtx->profile;
decoder->pix_fmt = vCtx->pix_fmt;
decoder->width = vCtx->width;
decoder->height = vCtx->height;
decoder->is_hw = 1;
decoder->frame_reorder = 1;
decoder->fini = fini_va_decoder;
return decoder;
return (struct decoder*)decoder;
err_2:
av_frame_free(&decoder->Frame);
err_1:
vaTerminate(dpy);
free(decoder);
vaTerminate(hw_decoder->dpy);
err_0:
drm_fd = 0;
return NULL;

View File

@ -134,7 +134,7 @@ int draw_frame(window_t *win)
int frame_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{
static pos_t spos;
static track_mode;
static int track_mode;
uint32_t cursor;
ctrl_t *child;