diff --git a/CMakeLists.txt b/CMakeLists.txt index 00dd129..0fa1fb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,7 +115,7 @@ endif() if(FREESCALE_FOUND) list(APPEND MOONLIGHT_DEFINITIONS HAVE_IMX) list(APPEND MOONLIGHT_OPTIONS IMX) - add_library(moonlight-imx SHARED ./src/video/imx.c) + add_library(moonlight-imx SHARED ./src/video/imx.c ./src/video/imx_vpu.c) target_include_directories(moonlight-imx PRIVATE ${FREESCALE_INCLUDE_DIRS} ${GAMESTREAM_INCLUDE_DIR} ${MOONLIGHT_COMMON_INCLUDE_DIR}) target_link_libraries(moonlight-imx gamestream ${FREESCALE_LIBRARIES}) install(TARGETS moonlight-imx DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/video/imx.c b/src/video/imx.c index 1dafbc9..6da0035 100644 --- a/src/video/imx.c +++ b/src/video/imx.c @@ -1,7 +1,7 @@ /* * This file is part of Moonlight Embedded. * - * Copyright (C) 2015 Iwan Timmer + * Copyright (C) 2015-2017 Iwan Timmer * * Moonlight is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,22 +17,19 @@ * along with Moonlight; if not, see . */ -#include +#include "imx_vpu.h" -#include #include -#include -#include -#include -#include +#include #include #include -#include #include #include #include +#include + #include #include #include @@ -40,47 +37,18 @@ #include #include -#include -#include - -#define STREAM_BUF_SIZE 0x200000 -#define PS_SAVE_SIZE 0x080000 - -#define MODE420 1 -#define MODE422 2 -#define MODE224 3 +#define MIN_FRAME_BUFFER_COUNT 18; #define THRESHOLD 2 -#define MIN_FRAME_BUFFER_COUNT 18; -#define WORST_SLICE_SIZE 3188 -struct v4l_buf { - void *start; - off_t offset; - size_t length; -}; +static int displaying; -static vpu_mem_desc mem_desc = {0}; -static vpu_mem_desc ps_mem_desc = {0}; -static vpu_mem_desc slice_mem_desc = {0}; - -static DecHandle handle = {0}; -static DecParam decparam = {0}; -static DecBufInfo bufinfo = {0}; static int fd; - -static int regfbcount, stride; - -static bool initialized = false, decoding = false, displaying = false; - static int queued_count; static int disp_clr_index = 0; -static FrameBuffer *fb; -static struct v4l2_buffer dbuf; - bool video_imx_init() { - return vpu_Init(NULL) == RETCODE_SUCCESS; + return vpu_init(); } static void decoder_renderer_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) { @@ -91,9 +59,6 @@ static void decoder_renderer_setup(int videoFormat, int width, int height, int r struct mxcfb_gbl_alpha alpha; - dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - dbuf.memory = V4L2_MEMORY_MMAP; - int fd_fb = open("/dev/fb0", O_RDWR, 0); if (fd_fb < 0){ @@ -110,73 +75,12 @@ static void decoder_renderer_setup(int videoFormat, int width, int height, int r close(fd_fb); - mem_desc.size = STREAM_BUF_SIZE; - if (IOGetPhyMem(&mem_desc)){ - fprintf(stderr, "Can't get physical memory address\n"); - exit(EXIT_FAILURE); - } - - if (IOGetVirtMem(&mem_desc) == -1) { - fprintf(stderr, "Can't get virtual memory address\n"); - exit(EXIT_FAILURE); - } - - ps_mem_desc.size = PS_SAVE_SIZE; - if (IOGetPhyMem(&ps_mem_desc)) { - fprintf(stderr, "Can't get physical memory address\n"); - exit(EXIT_FAILURE); - } - - DecOpenParam oparam = {0}; - oparam.bitstreamFormat = STD_AVC; - oparam.bitstreamBuffer = mem_desc.phy_addr; - oparam.bitstreamBufferSize = STREAM_BUF_SIZE; - oparam.pBitStream = (Uint8 *) mem_desc.virt_uaddr; - oparam.reorderEnable = 1; - oparam.mp4DeblkEnable = 0; - oparam.chromaInterleave = 0; - oparam.avcExtension = oparam.mp4Class = 0; - oparam.mjpg_thumbNailDecEnable = 0; - oparam.mapType = LINEAR_FRAME_MAP; - oparam.tiled2LinearEnable = 0; - oparam.bitstreamMode = 1; - - oparam.psSaveBuffer = ps_mem_desc.phy_addr; - oparam.psSaveBufferSize = PS_SAVE_SIZE; - - if (vpu_DecOpen(&handle, &oparam) != RETCODE_SUCCESS) { - fprintf(stderr, "Can't open video decoder\n"); - exit(EXIT_FAILURE); - } - - decparam.dispReorderBuf = 0; - decparam.skipframeMode = 0; - decparam.skipframeNum = 0; - decparam.iframeSearchEnable = 0; - - regfbcount = MIN_FRAME_BUFFER_COUNT + 2; + int regfbcount = MIN_FRAME_BUFFER_COUNT + 2; int picWidth = ((width + 15) & ~15); int picHeight = ((height + 15) & ~15); - stride = picWidth; - - int phy_slicebuf_size = WORST_SLICE_SIZE * 1024; - - slice_mem_desc.size = phy_slicebuf_size; - if (IOGetPhyMem(&slice_mem_desc)){ - fprintf(stderr, "Can't get slice physical address\n"); - exit(EXIT_FAILURE); - } - - fb = calloc(regfbcount, sizeof(FrameBuffer)); - if (fb == NULL) { - fprintf(stderr, "Can't allocate framebuffers\n"); - exit(EXIT_FAILURE); - } - - char v4l_device[16], node[8]; - sprintf(node, "%d", 17); - strcpy(v4l_device, "/dev/video"); - strcat(v4l_device, node); + + char v4l_device[16]; + sprintf(v4l_device, "/dev/video%d", 17); fd = open(v4l_device, O_RDWR, 0); if (fd < 0){ fprintf(stderr, "Can't access video output\n"); @@ -205,7 +109,7 @@ static void decoder_renderer_setup(int videoFormat, int width, int height, int r reqbuf.memory = V4L2_MEMORY_MMAP; reqbuf.count = regfbcount; - struct v4l_buf* buffers[regfbcount]; + struct vpu_buf* buffers[regfbcount]; if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) { fprintf(stderr, "Can't get video buffers\n"); @@ -219,9 +123,9 @@ static void decoder_renderer_setup(int videoFormat, int width, int height, int r for (int i = 0; i < regfbcount; i++) { struct v4l2_buffer buffer = {0}; - struct v4l_buf *buf; + struct vpu_buf *buf; - buf = calloc(1, sizeof(struct v4l_buf)); + buf = calloc(1, sizeof(struct vpu_buf)); if (buf == NULL) { fprintf(stderr, "Not enough memory\n"); exit(EXIT_FAILURE); @@ -257,185 +161,66 @@ static void decoder_renderer_setup(int videoFormat, int width, int height, int r exit(EXIT_FAILURE); } } - - int img_size = stride * picHeight; - vpu_mem_desc *mvcol_md = NULL; - - int mjpg_fmt = MODE420; - int divX = (mjpg_fmt == MODE420 || mjpg_fmt == MODE422) ? 2 : 1; - int divY = (mjpg_fmt == MODE420 || mjpg_fmt == MODE224) ? 2 : 1; - - mvcol_md = calloc(regfbcount, sizeof(vpu_mem_desc)); - - for (int i = 0; i < regfbcount; i++) { - fb[i].myIndex = i; - fb[i].bufY = buffers[i]->offset; - fb[i].bufCb = fb[i].bufY + img_size; - fb[i].bufCr = fb[i].bufCb + (img_size / divX / divY); - - /* allocate MvCol buffer here */ - memset(&mvcol_md[i], 0, sizeof(vpu_mem_desc)); - mvcol_md[i].size = img_size / divX / divY; - if (IOGetPhyMem(&mvcol_md[i])) { - fprintf(stderr, "Can't get physical address of colomn buffer\n"); - exit(EXIT_FAILURE); - } - fb[i].bufMvCol = mvcol_md[i].phy_addr; - } - - bufinfo.avcSliceBufInfo.bufferBase = slice_mem_desc.phy_addr; - bufinfo.avcSliceBufInfo.bufferSize = phy_slicebuf_size; - - bufinfo.maxDecFrmInfo.maxMbX = stride / 16; - bufinfo.maxDecFrmInfo.maxMbY = picHeight / 16; - bufinfo.maxDecFrmInfo.maxMbNum = stride * picHeight / 256; - - int delay = -1; - vpu_DecGiveCommand(handle, DEC_SET_FRAME_DELAY, &delay); + + vpu_setup(buffers, regfbcount, width, height); } static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) { - Uint32 space; - PhysicalAddress pa_read_ptr, pa_write_ptr; - if (vpu_DecGetBitstreamBuffer(handle, &pa_read_ptr, &pa_write_ptr, &space) != RETCODE_SUCCESS) { - fprintf(stderr, "Can't get video decoder buffer\n"); - exit(EXIT_FAILURE); - } - Uint32 target_addr = mem_desc.virt_uaddr + (pa_write_ptr - mem_desc.phy_addr); + if (vpu_decode(decodeUnit)) { + int frame = vpu_get_frame(); - if (space < decodeUnit->fullLength) { - fprintf(stderr, "Not enough space in buffer %d/%d\n", decodeUnit->fullLength, space); - } + struct timeval tv; + gettimeofday(&tv, 0); - PLENTRY entry = decodeUnit->bufferList; - int written = 0; - while (entry != NULL) { - if ( (target_addr + entry->length) > mem_desc.virt_uaddr + STREAM_BUF_SIZE) { - int room = mem_desc.virt_uaddr + STREAM_BUF_SIZE - target_addr; - memcpy((void *)target_addr, entry->data, room); - memcpy((void *)mem_desc.virt_uaddr, entry->data + room, entry->length - room); - target_addr = mem_desc.virt_uaddr + entry->length - room; - } else { - memcpy((void *)target_addr, entry->data, entry->length); - target_addr += entry->length; - } + struct v4l2_buffer dbuf = {}; + dbuf.timestamp.tv_sec = tv.tv_sec; + dbuf.timestamp.tv_usec = tv.tv_usec; + dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + dbuf.memory = V4L2_MEMORY_MMAP; - entry = entry->next; - } - vpu_DecUpdateBitstreamBuffer(handle, decodeUnit->fullLength); - - if (!initialized) { - initialized = true; - DecInitialInfo info = {0}; - vpu_DecSetEscSeqInit(handle, 1); - vpu_DecGetInitialInfo(handle, &info); - vpu_DecSetEscSeqInit(handle, 0); - if (vpu_DecRegisterFrameBuffer(handle, fb, regfbcount, stride, &bufinfo) != RETCODE_SUCCESS) { - fprintf(stderr, "Can't register decoder to framebuffer\n"); - exit(EXIT_FAILURE); - } - } - - if (!decoding) { - if (vpu_DecStartOneFrame(handle, &decparam) != RETCODE_SUCCESS) { - fprintf(stderr, "Can't start decoding\n"); - exit(EXIT_FAILURE); - } - decoding = true; - } - - int loop_id = 0; - while (vpu_IsBusy()) { - if (loop_id > 50) { - vpu_SWReset(handle, 0); - fprintf(stderr, "VPU is too long busy\n"); - exit(EXIT_FAILURE); - } - vpu_WaitForInt(100); - loop_id++; - } - - if (decoding) { - decoding = 0; - - DecOutputInfo outinfo = {0}; - if (vpu_DecGetOutputInfo(handle, &outinfo) != RETCODE_SUCCESS) { - fprintf(stderr, "Can't get output info\n"); + dbuf.index = frame; + if (ioctl(fd, VIDIOC_QUERYBUF, &dbuf) < 0) { + fprintf(stderr, "Can't get output buffer\n"); exit(EXIT_FAILURE); } - if (outinfo.decodingSuccess & 0x10) { - return DR_OK; - } else if (outinfo.notSufficientPsBuffer) { - fprintf(stderr, "Not enough space in stream buffer\n"); - exit(EXIT_FAILURE); - } else if (outinfo.notSufficientSliceBuffer) { - fprintf(stderr, "Not enough space in slice buffer\n"); + dbuf.index = frame; + dbuf.field = V4L2_FIELD_NONE; + if (ioctl(fd, VIDIOC_QBUF, &dbuf) < 0) { + fprintf(stderr, "Can't get output buffer\n"); exit(EXIT_FAILURE); } - if (outinfo.indexFrameDisplay >= 0) { - struct timeval tv; - gettimeofday(&tv, 0); - dbuf.timestamp.tv_sec = tv.tv_sec; - dbuf.timestamp.tv_usec = tv.tv_usec; + if (!displaying) { + int type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { + fprintf(stderr, "Failed to output video\n"); + exit(EXIT_FAILURE); + } + displaying = true; + } + + queued_count++; + + if (queued_count > THRESHOLD) { dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; dbuf.memory = V4L2_MEMORY_MMAP; - - dbuf.index = outinfo.indexFrameDisplay; - if (ioctl(fd, VIDIOC_QUERYBUF, &dbuf) < 0) { - fprintf(stderr, "Can't get output buffer\n"); + if (ioctl(fd, VIDIOC_DQBUF, &dbuf) < 0) { + fprintf(stderr, "Failed to dequeue buffer\n"); exit(EXIT_FAILURE); - } - - dbuf.index = outinfo.indexFrameDisplay; - dbuf.field = V4L2_FIELD_NONE; - if (ioctl(fd, VIDIOC_QBUF, &dbuf) < 0) { - fprintf(stderr, "Can't get output buffer\n"); - exit(EXIT_FAILURE); - } - - if (!displaying) { - int type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { - fprintf(stderr, "Failed to output video\n"); - exit(EXIT_FAILURE); - } - displaying = true; - } - - queued_count++; - - if (queued_count > THRESHOLD) { - dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - dbuf.memory = V4L2_MEMORY_MMAP; - if (ioctl(fd, VIDIOC_DQBUF, &dbuf) < 0) { - fprintf(stderr, "Failed to dequeue buffer\n"); - exit(EXIT_FAILURE); - } else - queued_count--; - } - - if (disp_clr_index >= 0) - vpu_DecClrDispFlag(handle, disp_clr_index); - - disp_clr_index = outinfo.indexFrameDisplay; - } else if (outinfo.indexFrameDisplay == -1) { - fprintf(stderr, "Failed to decode frame\n"); - exit(EXIT_FAILURE); + } else + queued_count--; } - } - return DR_OK; + if (disp_clr_index >= 0) + vpu_clear(disp_clr_index); + + disp_clr_index = frame; + } } static void decoder_renderer_cleanup() { - IOFreePhyMem(&ps_mem_desc); - IOFreePhyMem(&slice_mem_desc); - - IOFreeVirtMem(&mem_desc); - IOFreePhyMem(&mem_desc); - vpu_UnInit(); + vpu_cleanup(); } DECODER_RENDERER_CALLBACKS decoder_callbacks_imx = { diff --git a/src/video/imx_vpu.c b/src/video/imx_vpu.c new file mode 100644 index 0000000..ca88660 --- /dev/null +++ b/src/video/imx_vpu.c @@ -0,0 +1,256 @@ +/* + * This file is part of Moonlight Embedded. + * + * Copyright (C) 2015-2017 Iwan Timmer + * + * Moonlight is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Moonlight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Moonlight; if not, see . + */ + +#include "imx_vpu.h" + +#include +#include +#include +#include + +#include +#include + +#define STREAM_BUF_SIZE 0x200000 +#define PS_SAVE_SIZE 0x080000 + +#define MODE420 1 +#define MODE422 2 +#define MODE224 3 + +#define WORST_SLICE_SIZE 3188 + +static vpu_mem_desc mem_desc = {0}; +static vpu_mem_desc ps_mem_desc = {0}; +static vpu_mem_desc slice_mem_desc = {0}; + +static DecHandle handle = {0}; +static DecParam decparam = {0}; +static DecBufInfo bufinfo = {0}; + +static int regfbcount, stride; + +static bool initialized = false; + +static FrameBuffer *fb; + +static int currentFrame; + +bool vpu_init() { + return vpu_Init(NULL) == RETCODE_SUCCESS; +} + +void vpu_setup(struct vpu_buf* buffers[], int bufferCount, int width, int height) { + mem_desc.size = STREAM_BUF_SIZE; + if (IOGetPhyMem(&mem_desc)){ + fprintf(stderr, "Can't get physical memory address\n"); + exit(EXIT_FAILURE); + } + + if (IOGetVirtMem(&mem_desc) == -1) { + fprintf(stderr, "Can't get virtual memory address\n"); + exit(EXIT_FAILURE); + } + + ps_mem_desc.size = PS_SAVE_SIZE; + if (IOGetPhyMem(&ps_mem_desc)) { + fprintf(stderr, "Can't get physical memory address\n"); + exit(EXIT_FAILURE); + } + + DecOpenParam oparam = {0}; + oparam.bitstreamFormat = STD_AVC; + oparam.bitstreamBuffer = mem_desc.phy_addr; + oparam.bitstreamBufferSize = STREAM_BUF_SIZE; + oparam.pBitStream = (Uint8 *) mem_desc.virt_uaddr; + oparam.reorderEnable = 1; + oparam.mp4DeblkEnable = 0; + oparam.chromaInterleave = 0; + oparam.avcExtension = oparam.mp4Class = 0; + oparam.mjpg_thumbNailDecEnable = 0; + oparam.mapType = LINEAR_FRAME_MAP; + oparam.tiled2LinearEnable = 0; + oparam.bitstreamMode = 1; + + oparam.psSaveBuffer = ps_mem_desc.phy_addr; + oparam.psSaveBufferSize = PS_SAVE_SIZE; + + if (vpu_DecOpen(&handle, &oparam) != RETCODE_SUCCESS) { + fprintf(stderr, "Can't open video decoder\n"); + exit(EXIT_FAILURE); + } + + decparam.dispReorderBuf = 0; + decparam.skipframeMode = 0; + decparam.skipframeNum = 0; + decparam.iframeSearchEnable = 0; + + int phy_slicebuf_size = WORST_SLICE_SIZE * 1024; + + slice_mem_desc.size = phy_slicebuf_size; + if (IOGetPhyMem(&slice_mem_desc)){ + fprintf(stderr, "Can't get slice physical address\n"); + exit(EXIT_FAILURE); + } + + regfbcount = bufferCount; + + fb = calloc(regfbcount, sizeof(FrameBuffer)); + if (fb == NULL) { + fprintf(stderr, "Can't allocate framebuffers\n"); + exit(EXIT_FAILURE); + } + + stride = ((width + 15) & ~15); + int picHeight = ((height + 15) & ~15); + int img_size = stride * picHeight; + vpu_mem_desc *mvcol_md = NULL; + + int mjpg_fmt = MODE420; + int divX = (mjpg_fmt == MODE420 || mjpg_fmt == MODE422) ? 2 : 1; + int divY = (mjpg_fmt == MODE420 || mjpg_fmt == MODE224) ? 2 : 1; + + mvcol_md = calloc(regfbcount, sizeof(vpu_mem_desc)); + + for (int i = 0; i < regfbcount; i++) { + fb[i].myIndex = i; + fb[i].bufY = buffers[i]->offset; + fb[i].bufCb = fb[i].bufY + img_size; + fb[i].bufCr = fb[i].bufCb + (img_size / divX / divY); + + /* allocate MvCol buffer here */ + memset(&mvcol_md[i], 0, sizeof(vpu_mem_desc)); + mvcol_md[i].size = img_size / divX / divY; + if (IOGetPhyMem(&mvcol_md[i])) { + fprintf(stderr, "Can't get physical address of colomn buffer\n"); + exit(EXIT_FAILURE); + } + fb[i].bufMvCol = mvcol_md[i].phy_addr; + } + + bufinfo.avcSliceBufInfo.bufferBase = slice_mem_desc.phy_addr; + bufinfo.avcSliceBufInfo.bufferSize = phy_slicebuf_size; + + bufinfo.maxDecFrmInfo.maxMbX = stride / 16; + bufinfo.maxDecFrmInfo.maxMbY = picHeight / 16; + bufinfo.maxDecFrmInfo.maxMbNum = stride * picHeight / 256; + + int delay = -1; + vpu_DecGiveCommand(handle, DEC_SET_FRAME_DELAY, &delay); +} + +int vpu_get_frame() { + return currentFrame; +} + +bool vpu_decode(PDECODE_UNIT decodeUnit) { + Uint32 space; + PhysicalAddress pa_read_ptr, pa_write_ptr; + if (vpu_DecGetBitstreamBuffer(handle, &pa_read_ptr, &pa_write_ptr, &space) != RETCODE_SUCCESS) { + fprintf(stderr, "Can't get video decoder buffer\n"); + exit(EXIT_FAILURE); + } + Uint32 target_addr = mem_desc.virt_uaddr + (pa_write_ptr - mem_desc.phy_addr); + + if (space < decodeUnit->fullLength) { + fprintf(stderr, "Not enough space in buffer %d/%d\n", decodeUnit->fullLength, space); + } + + PLENTRY entry = decodeUnit->bufferList; + int written = 0; + while (entry != NULL) { + if ( (target_addr + entry->length) > mem_desc.virt_uaddr + STREAM_BUF_SIZE) { + int room = mem_desc.virt_uaddr + STREAM_BUF_SIZE - target_addr; + memcpy((void *)target_addr, entry->data, room); + memcpy((void *)mem_desc.virt_uaddr, entry->data + room, entry->length - room); + target_addr = mem_desc.virt_uaddr + entry->length - room; + } else { + memcpy((void *)target_addr, entry->data, entry->length); + target_addr += entry->length; + } + + entry = entry->next; + } + vpu_DecUpdateBitstreamBuffer(handle, decodeUnit->fullLength); + + if (!initialized) { + initialized = true; + DecInitialInfo info = {0}; + vpu_DecSetEscSeqInit(handle, 1); + vpu_DecGetInitialInfo(handle, &info); + vpu_DecSetEscSeqInit(handle, 0); + if (vpu_DecRegisterFrameBuffer(handle, fb, regfbcount, stride, &bufinfo) != RETCODE_SUCCESS) { + fprintf(stderr, "Can't register decoder to framebuffer\n"); + exit(EXIT_FAILURE); + } + } + + if (vpu_DecStartOneFrame(handle, &decparam) != RETCODE_SUCCESS) { + fprintf(stderr, "Can't start decoding\n"); + exit(EXIT_FAILURE); + } + + int loop_id = 0; + while (vpu_IsBusy()) { + if (loop_id > 50) { + vpu_SWReset(handle, 0); + fprintf(stderr, "VPU is too long busy\n"); + exit(EXIT_FAILURE); + } + vpu_WaitForInt(100); + loop_id++; + } + + DecOutputInfo outinfo = {0}; + if (vpu_DecGetOutputInfo(handle, &outinfo) != RETCODE_SUCCESS) { + fprintf(stderr, "Can't get output info\n"); + exit(EXIT_FAILURE); + } + + if (outinfo.decodingSuccess & 0x10) { + return false; + } else if (outinfo.notSufficientPsBuffer) { + fprintf(stderr, "Not enough space in stream buffer\n"); + exit(EXIT_FAILURE); + } else if (outinfo.notSufficientSliceBuffer) { + fprintf(stderr, "Not enough space in slice buffer\n"); + exit(EXIT_FAILURE); + } + + if (outinfo.indexFrameDisplay < 0) { + fprintf(stderr, "Failed to decode frame\n"); + exit(EXIT_FAILURE); + } + + currentFrame = outinfo.indexFrameDisplay; + return true; +} + +void vpu_clear(int disp_clr_index) { + vpu_DecClrDispFlag(handle, disp_clr_index); +} + +void vpu_cleanup() { + IOFreePhyMem(&ps_mem_desc); + IOFreePhyMem(&slice_mem_desc); + + IOFreeVirtMem(&mem_desc); + IOFreePhyMem(&mem_desc); + vpu_UnInit(); +} diff --git a/src/video/imx_vpu.h b/src/video/imx_vpu.h new file mode 100644 index 0000000..2d8b41e --- /dev/null +++ b/src/video/imx_vpu.h @@ -0,0 +1,39 @@ +/* + * This file is part of Moonlight Embedded. + * + * Copyright (C) 2017 Iwan Timmer + * + * Moonlight is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Moonlight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Moonlight; if not, see . + */ + +#include + +#include + +#include + +struct vpu_buf { + void *start; + off_t offset; + size_t length; +}; + +bool vpu_init(); +void vpu_setup(struct vpu_buf* buffers[], int bufferCount, int stride, int height); + +bool vpu_decode(PDECODE_UNIT decodeUnit); +int vpu_get_frame(); +void vpu_clear(int disp_clr_index); + +void vpu_cleanup();