diff --git a/contrib/media/fplay/Makefile b/contrib/media/fplay/Makefile index 3baffc3864..06c27e6913 100644 --- a/contrib/media/fplay/Makefile +++ b/contrib/media/fplay/Makefile @@ -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 diff --git a/contrib/media/fplay/decoder.c b/contrib/media/fplay/decoder.c index 15e80b6900..979768d92a 100644 --- a/contrib/media/fplay/decoder.c +++ b/contrib/media/fplay/decoder.c @@ -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; +} + diff --git a/contrib/media/fplay/fplay.c b/contrib/media/fplay/fplay.c index 3ee93e1c78..01bedd1d0f 100644 --- a/contrib/media/fplay/fplay.c +++ b/contrib/media/fplay/fplay.c @@ -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); diff --git a/contrib/media/fplay/fplay.h b/contrib/media/fplay/fplay.h index 9e05952923..e6f871aeab 100644 --- a/contrib/media/fplay/fplay.h +++ b/contrib/media/fplay/fplay.h @@ -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__) + diff --git a/contrib/media/fplay/utils.c b/contrib/media/fplay/utils.c index 89a0a2bd9c..59034b9377 100644 --- a/contrib/media/fplay/utils.c +++ b/contrib/media/fplay/utils.c @@ -1,8 +1,9 @@ - +#include #include #include #include #include +#include #include #include #include "winlib/winlib.h" diff --git a/contrib/media/fplay/vaapi.c b/contrib/media/fplay/vaapi.c index 8cb3111640..5718a0f819 100644 --- a/contrib/media/fplay/vaapi.c +++ b/contrib/media/fplay/vaapi.c @@ -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; diff --git a/contrib/media/fplay/winlib/frame.c b/contrib/media/fplay/winlib/frame.c index 4f8cac001b..64a728ce7a 100644 --- a/contrib/media/fplay/winlib/frame.c +++ b/contrib/media/fplay/winlib/frame.c @@ -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;