diff --git a/src/util.c b/src/util.c index 1b9b652..b6442ba 100644 --- a/src/util.c +++ b/src/util.c @@ -24,6 +24,7 @@ #include #include #include +#include int write_bool(char *path, bool val) { int fd = open(path, O_RDWR); @@ -50,3 +51,16 @@ int read_file(char *path, char* output, int output_len) { return -1; } +bool ensure_buf_size(void **buf, size_t *buf_size, size_t required_size) { + if (*buf_size >= required_size) + return false; + + *buf_size = required_size; + *buf = realloc(*buf, *buf_size); + if (!*buf) { + fprintf(stderr, "Failed to allocate %zu bytes\n", *buf_size); + abort(); + } + + return true; +} \ No newline at end of file diff --git a/src/util.h b/src/util.h index 3a394d2..adad8de 100644 --- a/src/util.h +++ b/src/util.h @@ -18,6 +18,8 @@ */ #include +#include int write_bool(char *path, bool val); int read_file(char *path, char *output, int output_len); +bool ensure_buf_size(void **buf, size_t *buf_size, size_t required_size); diff --git a/src/video/mmal.c b/src/video/mmal.c index e599742..89ae70c 100644 --- a/src/video/mmal.c +++ b/src/video/mmal.c @@ -48,8 +48,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#define MAX_DECODE_UNIT_SIZE 262144 - #define ALIGN(x, a) (((x)+(a)-1)&~((a)-1)) static VCOS_SEMAPHORE_T semaphore; @@ -116,7 +114,7 @@ static int decoder_renderer_setup(int videoFormat, int width, int height, int re } decoder->input[0]->buffer_num = 5; - decoder->input[0]->buffer_size = MAX_DECODE_UNIT_SIZE; + decoder->input[0]->buffer_size = INITIAL_DECODER_BUFFER_SIZE; pool_in = mmal_port_pool_create(decoder->input[0], decoder->input[0]->buffer_num, decoder->output[0]->buffer_size); MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format; diff --git a/src/video/pi.c b/src/video/pi.c index a57fe59..4cc443a 100644 --- a/src/video/pi.c +++ b/src/video/pi.c @@ -41,8 +41,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#define MAX_DECODE_UNIT_SIZE 262144 - static TUNNEL_T tunnel[2]; static COMPONENT_T *list[3]; static ILCLIENT_T *client; @@ -179,7 +177,7 @@ static int decoder_renderer_setup(int videoFormat, int width, int height, int re } // Increase the buffer size to fit the largest possible frame - port.nBufferSize = MAX_DECODE_UNIT_SIZE; + port.nBufferSize = INITIAL_DECODER_BUFFER_SIZE; if(OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamPortDefinition, &port) == OMX_ErrorNone && ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0) { diff --git a/src/video/rk.c b/src/video/rk.c index bcd6949..d24a5a3 100644 --- a/src/video/rk.c +++ b/src/video/rk.c @@ -18,7 +18,8 @@ * along with Moonlight; if not, see . */ -#include +#include "video.h" +#include "../util.h" #include #include @@ -38,7 +39,6 @@ #include -#define READ_BUF_SIZE 0x00100000 #define MAX_FRAMES 16 #define RK_H264 7 #define RK_H265 16777220 @@ -48,6 +48,7 @@ #endif void *pkt_buf = NULL; +size_t pkt_buf_size = 0; int fd; int fb_id; uint32_t plane_id, crtc_id; @@ -362,9 +363,9 @@ int rk_setup(int videoFormat, int width, int height, int redrawRate, void* conte // MPI SETUP - pkt_buf = malloc(READ_BUF_SIZE); + pkt_buf = ensure_buf_size(&pkt_buf, &pkt_buf_size, INITIAL_DECODER_BUFFER_SIZE); assert(pkt_buf); - ret = mpp_packet_init(&mpi_packet, pkt_buf, READ_BUF_SIZE); + ret = mpp_packet_init(&mpi_packet, pkt_buf, pkt_buf_size); assert(!ret); ret = mpp_create(&mpi_ctx, &mpi_api); @@ -455,25 +456,26 @@ void rk_cleanup() { int rk_submit_decode_unit(PDECODE_UNIT decodeUnit) { int result = DR_OK; + PLENTRY entry = decodeUnit->bufferList; + int length = 0; - if (decodeUnit->fullLength < READ_BUF_SIZE) { - PLENTRY entry = decodeUnit->bufferList; - int length = 0; - while (entry != NULL) { - memcpy(pkt_buf+length, entry->data, entry->length); - length += entry->length; - entry = entry->next; - } - if (length) { - mpp_packet_set_pos(mpi_packet, pkt_buf); - mpp_packet_set_length(mpi_packet, length); - - while (MPP_OK != mpi_api->decode_put_packet(mpi_ctx, mpi_packet)) - ; - - } + if (ensure_buf_size(&pkt_buf, &pkt_buf_size, decodeUnit->fullLength)) { + // Buffer was reallocated, so update the mpp_packet accordingly + mpp_packet_set_data(mpi_packet, pkt_buf); + mpp_packet_set_size(mpi_packet, pkt_buf_size); } + while (entry != NULL) { + memcpy(pkt_buf+length, entry->data, entry->length); + length += entry->length; + entry = entry->next; + } + + mpp_packet_set_pos(mpi_packet, pkt_buf); + mpp_packet_set_length(mpi_packet, length); + + while (MPP_OK != mpi_api->decode_put_packet(mpi_ctx, mpi_packet)); + return result; } diff --git a/src/video/sdl.c b/src/video/sdl.c index 0e5bf6a..1a7f6cf 100644 --- a/src/video/sdl.c +++ b/src/video/sdl.c @@ -21,6 +21,7 @@ #include "ffmpeg.h" #include "../sdl.h" +#include "../util.h" #include #include @@ -28,10 +29,10 @@ #include #include -#define DECODER_BUFFER_SIZE 256*1024 #define SLICES_PER_FRAME 4 -static char* ffmpeg_buffer; +static void* ffmpeg_buffer; +static size_t ffmpeg_buffer_size; static int sdl_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) { if (ffmpeg_init(videoFormat, width, height, SLICE_THREADING, SDL_BUFFER_FRAMES, SLICES_PER_FRAME) < 0) { @@ -39,12 +40,7 @@ static int sdl_setup(int videoFormat, int width, int height, int redrawRate, voi return -1; } - ffmpeg_buffer = malloc(DECODER_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); - if (ffmpeg_buffer == NULL) { - fprintf(stderr, "Not enough memory\n"); - ffmpeg_destroy(); - return -1; - } + ensure_buf_size(&ffmpeg_buffer, &ffmpeg_buffer_size, INITIAL_DECODER_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); return 0; } @@ -54,36 +50,31 @@ static void sdl_cleanup() { } static int sdl_submit_decode_unit(PDECODE_UNIT decodeUnit) { - if (decodeUnit->fullLength < DECODER_BUFFER_SIZE) { - PLENTRY entry = decodeUnit->bufferList; - int length = 0; - while (entry != NULL) { - memcpy(ffmpeg_buffer+length, entry->data, entry->length); - length += entry->length; - entry = entry->next; - } - ffmpeg_decode(ffmpeg_buffer, length); + PLENTRY entry = decodeUnit->bufferList; + int length = 0; - if (SDL_LockMutex(mutex) == 0) { - AVFrame* frame = ffmpeg_get_frame(false); - if (frame != NULL) { - sdlNextFrame++; + ensure_buf_size(&ffmpeg_buffer, &ffmpeg_buffer_size, decodeUnit->fullLength + AV_INPUT_BUFFER_PADDING_SIZE); - SDL_Event event; - event.type = SDL_USEREVENT; - event.user.code = SDL_CODE_FRAME; - event.user.data1 = &frame->data; - event.user.data2 = &frame->linesize; - SDL_PushEvent(&event); - } - - SDL_UnlockMutex(mutex); - } else - fprintf(stderr, "Couldn't lock mutex\n"); - } else { - fprintf(stderr, "Video decode buffer too small"); - exit(1); + while (entry != NULL) { + memcpy(ffmpeg_buffer+length, entry->data, entry->length); + length += entry->length; + entry = entry->next; } + ffmpeg_decode(ffmpeg_buffer, length); + + SDL_LockMutex(mutex); + AVFrame* frame = ffmpeg_get_frame(false); + if (frame != NULL) { + sdlNextFrame++; + + SDL_Event event; + event.type = SDL_USEREVENT; + event.user.code = SDL_CODE_FRAME; + event.user.data1 = &frame->data; + event.user.data2 = &frame->linesize; + SDL_PushEvent(&event); + } + SDL_UnlockMutex(mutex); return DR_OK; } diff --git a/src/video/video.h b/src/video/video.h index a5564fb..4c1344b 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -33,6 +33,8 @@ #define INIT_VDPAU 2 #define INIT_VAAPI 3 +#define INITIAL_DECODER_BUFFER_SIZE (256*1024) + #ifdef HAVE_X11 int x11_init(bool vdpau, bool vaapi); extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11; diff --git a/src/video/x11.c b/src/video/x11.c index 31ecffa..80c586c 100644 --- a/src/video/x11.c +++ b/src/video/x11.c @@ -26,6 +26,7 @@ #include "../input/x11.h" #include "../loop.h" +#include "../util.h" #include #include @@ -37,12 +38,12 @@ #include #include -#define DECODER_BUFFER_SIZE 256*1024 #define X11_VDPAU_ACCELERATION ENABLE_HARDWARE_ACCELERATION_1 #define X11_VAAPI_ACCELERATION ENABLE_HARDWARE_ACCELERATION_2 #define SLICES_PER_FRAME 4 -static char* ffmpeg_buffer = NULL; +static void* ffmpeg_buffer = NULL; +static size_t ffmpeg_buffer_size = 0; static Display *display = NULL; static Window window; @@ -82,11 +83,7 @@ int x11_init(bool vdpau, bool vaapi) { } int x11_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) { - ffmpeg_buffer = malloc(DECODER_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); - if (ffmpeg_buffer == NULL) { - fprintf(stderr, "Not enough memory\n"); - return -1; - } + ensure_buf_size(&ffmpeg_buffer, &ffmpeg_buffer_size, INITIAL_DECODER_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); if (!display) { fprintf(stderr, "Error: failed to open X display.\n"); @@ -167,20 +164,23 @@ void x11_cleanup() { } int x11_submit_decode_unit(PDECODE_UNIT decodeUnit) { - if (decodeUnit->fullLength < DECODER_BUFFER_SIZE) { - PLENTRY entry = decodeUnit->bufferList; - int length = 0; - while (entry != NULL) { - memcpy(ffmpeg_buffer+length, entry->data, entry->length); - length += entry->length; - entry = entry->next; - } - ffmpeg_decode(ffmpeg_buffer, length); - AVFrame* frame = ffmpeg_get_frame(true); - if (frame != NULL) - write(pipefd[1], &frame, sizeof(void*)); + PLENTRY entry = decodeUnit->bufferList; + int length = 0; + + ensure_buf_size(&ffmpeg_buffer, &ffmpeg_buffer_size, decodeUnit->fullLength + AV_INPUT_BUFFER_PADDING_SIZE); + + while (entry != NULL) { + memcpy(ffmpeg_buffer+length, entry->data, entry->length); + length += entry->length; + entry = entry->next; } + ffmpeg_decode(ffmpeg_buffer, length); + + AVFrame* frame = ffmpeg_get_frame(true); + if (frame != NULL) + write(pipefd[1], &frame, sizeof(void*)); + return DR_OK; }