Skip to content

Commit

Permalink
8292097: Better video decoding
Browse files Browse the repository at this point in the history
Reviewed-by: kcr, rhalade, arapte
  • Loading branch information
Alexander Matveev authored and kevinrushforth committed Jan 17, 2023
1 parent 2e17f7a commit 09a7f9a
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 30 deletions.
Expand Up @@ -680,6 +680,8 @@ static GstFlowReturn videodecoder_chain(GstPad *pad, GstObject *parent, GstBuffe
gboolean unmap_buf = FALSE;
gboolean set_frame_values = TRUE;
int64_t reordered_opaque = AV_NOPTS_VALUE;
unsigned int out_buf_size = 0;
gboolean copy_error = FALSE;
uint8_t* data0 = NULL;
uint8_t* data1 = NULL;
uint8_t* data2 = NULL;
Expand Down Expand Up @@ -811,12 +813,59 @@ static GstFlowReturn videodecoder_chain(GstPad *pad, GstObject *parent, GstBuffe
}

// Copy image by parts from different arrays.
memcpy(info2.data, data0, decoder->u_offset);
memcpy(info2.data + decoder->u_offset, data1, decoder->uv_blocksize);
memcpy(info2.data + decoder->v_offset, data2, decoder->uv_blocksize);
if (decoder->frame_size > (unsigned int)info2.maxsize) // maxsize should be same or more due to alignment
{
gst_buffer_unmap(outbuf, &info2);
// INLINE - gst_buffer_unref()
gst_buffer_unref(outbuf);
gst_element_message_full(GST_ELEMENT(decoder), GST_MESSAGE_ERROR, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NO_SPACE_LEFT,
g_strdup("Wrong buffer size"), NULL, ("videodecoder.c"), ("videodecoder_chain"), 0);
goto _exit;
}

out_buf_size = decoder->frame_size;
if (out_buf_size >= decoder->u_offset)
{
memcpy(info2.data, data0, decoder->u_offset);
out_buf_size -= decoder->u_offset;
if (out_buf_size >= decoder->uv_blocksize &&
decoder->uv_blocksize <= decoder->frame_size &&
decoder->u_offset <= (decoder->frame_size - decoder->uv_blocksize))
{
memcpy(info2.data + decoder->u_offset, data1, decoder->uv_blocksize);
out_buf_size -= decoder->uv_blocksize;
if (out_buf_size >= decoder->uv_blocksize &&
decoder->uv_blocksize <= decoder->frame_size &&
decoder->v_offset <= (decoder->frame_size - decoder->uv_blocksize))
{
memcpy(info2.data + decoder->v_offset, data2, decoder->uv_blocksize);
}
else
{
copy_error = TRUE;
}
}
else
{
copy_error = TRUE;
}
}
else
{
copy_error = TRUE;
}

gst_buffer_unmap(outbuf, &info2);

if (copy_error)
{
// INLINE - gst_buffer_unref()
gst_buffer_unref(outbuf);
gst_element_message_full(GST_ELEMENT(decoder), GST_MESSAGE_ERROR, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NO_SPACE_LEFT,
g_strdup("Copy data failed"), NULL, ("videodecoder.c"), ("videodecoder_chain"), 0);
goto _exit;
}

GST_BUFFER_OFFSET_END(outbuf) = GST_BUFFER_OFFSET_NONE;

if (decoder->discont || GST_BUFFER_IS_DISCONT(buf))
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -67,19 +67,19 @@ typedef struct _VideoDecoderClass VideoDecoderClass;
struct _VideoDecoder {
BaseDecoder parent;

gint width;
gint height;
int frame_finished;
gboolean discont;
gint width;
gint height;
int frame_finished;
gboolean discont;

int frame_size; // in bytes
int u_offset;
int v_offset;
int uv_blocksize;
unsigned int frame_size; // in bytes
unsigned int u_offset;
unsigned int v_offset;
unsigned int uv_blocksize;

AVPacket packet;
AVPacket packet;

gint codec_id;
gint codec_id;

#if HEVC_SUPPORT
struct SwsContext *sws_context;
Expand Down
Expand Up @@ -357,7 +357,7 @@ static void mfwrapper_set_src_caps(GstMFWrapper *decoder)
}
}

static void mfwrapper_nalu_to_start_code(BYTE *pbBuffer, guint size)
static void mfwrapper_nalu_to_start_code(BYTE *pbBuffer, gsize size)
{
gint leftSize = size;

Expand Down Expand Up @@ -389,9 +389,9 @@ static gboolean mfwrapper_process_input(GstMFWrapper *decoder, GstBuffer *buf)
{
IMFSample *pSample = NULL;
IMFMediaBuffer *pBuffer = NULL;
DWORD dwBufferSize = 0;
BYTE *pbBuffer = NULL;
GstMapInfo info;
gsize size = 0;
gboolean unmap_buf = FALSE;
gboolean unlock_buf = FALSE;

Expand All @@ -418,9 +418,15 @@ static gboolean mfwrapper_process_input(GstMFWrapper *decoder, GstBuffer *buf)
hr = E_FAIL;

if (SUCCEEDED(hr) && decoder->header != NULL && decoder->header_size > 0)
hr = MFCreateMemoryBuffer(decoder->header_size + info.size, &pBuffer);
dwBufferSize = (DWORD)decoder->header_size + (DWORD)info.size;
else if (SUCCEEDED(hr))
hr = MFCreateMemoryBuffer(info.size, &pBuffer);
dwBufferSize = (DWORD)info.size;

if (SUCCEEDED(hr))
hr = MFCreateMemoryBuffer(dwBufferSize, &pBuffer);

if (SUCCEEDED(hr))
hr = pBuffer->SetCurrentLength(dwBufferSize);

if (SUCCEEDED(hr))
hr = pBuffer->Lock(&pbBuffer, NULL, NULL);
Expand All @@ -430,22 +436,38 @@ static gboolean mfwrapper_process_input(GstMFWrapper *decoder, GstBuffer *buf)

if (SUCCEEDED(hr) && decoder->header != NULL && decoder->header_size > 0)
{
memcpy_s(pbBuffer, decoder->header_size + info.size, decoder->header, decoder->header_size);
pbBuffer += decoder->header_size;
memcpy_s(pbBuffer, info.size, info.data, info.size);
mfwrapper_nalu_to_start_code(pbBuffer, info.size);

delete[] decoder->header;
decoder->header = NULL;
if (dwBufferSize >= decoder->header_size)
{
memcpy_s(pbBuffer, dwBufferSize, decoder->header, decoder->header_size);
pbBuffer += decoder->header_size;
dwBufferSize -= decoder->header_size;

hr = pBuffer->SetCurrentLength(decoder->header_size + info.size);
decoder->header_size = 0;
if (dwBufferSize >= info.size)
{
memcpy_s(pbBuffer, dwBufferSize, info.data, info.size);
mfwrapper_nalu_to_start_code(pbBuffer, info.size);
}
else
{
hr = E_FAIL;
}
}
else
{
hr = E_FAIL;
}
}
else if (SUCCEEDED(hr))
{
memcpy_s(pbBuffer, info.size, info.data, info.size);
memcpy_s(pbBuffer, dwBufferSize, info.data, info.size);
mfwrapper_nalu_to_start_code(pbBuffer, info.size);
hr = pBuffer->SetCurrentLength(info.size);
}

if (decoder->header != NULL)
{
delete[] decoder->header;
decoder->header = NULL;
decoder->header_size = 0;
}

if (unlock_buf)
Expand Down
Expand Up @@ -76,7 +76,7 @@ struct _GstMFWrapper
IMFSample *pColorConvertOutput;

BYTE *header;
guint header_size;
gsize header_size;

guint width;
guint height;
Expand Down

0 comments on commit 09a7f9a

Please sign in to comment.