Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Duck IVF parsing support to the elementary stream. #18

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 78 additions & 5 deletions vk_video_decoder/libs/VkDecoderUtils/ElementaryStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#include <fstream>
#include "mio/mio.hpp"
#include "VkDecoderUtils/VideoStreamDemuxer.h"
#define DKIF_FRAME_CONTAINER_HEADER_SIZE 12
#define DKIF_HEADER_MAGIC *((const uint32_t*)"DKIF")
#define DKIF_FILE_HEADER_SIZE 32
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to use structure and get some information from the header such as the codec.
You can get inspiration from https://github.com/Igalia/ESExtractor/blob/main/lib/eseivfstream.cpp

#define USE_SIMPLE_MALLOC 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused about this USE_SIMPLE_MALLOC. Can you add a comment to explain the use of that ?


class ElementaryStream : public VideoStreamDemuxer {

Expand All @@ -32,11 +36,38 @@ class ElementaryStream : public VideoStreamDemuxer {
, m_height(defaultHeight)
, m_bitDepth(defaultBitDepth)
, m_videoCodecType(forceParserType)
#ifndef USE_SIMPLE_MALLOC
, m_inputVideoStreamMmap()
#endif
, m_pBitstreamData(nullptr)
, m_bitstreamDataSize(0)
, m_bytesRead(0) {

#ifdef USE_SIMPLE_MALLOC
FILE* handle = fopen(pFilePath, "rb");
if (handle == nullptr) {
printf("Failed to open video file %s\n", pFilePath);
m_bitstreamDataSize = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for that as its already set to null and zero above

m_pBitstreamData = nullptr;
return;
}

fseek(handle, 0, SEEK_END);
size_t size = ftell(handle);
uint8_t* data = (uint8_t*)malloc(size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid this approach for very large file. I would read the size of the frame by the frame header and move the offset to this size.


if (data == nullptr) {
printf("Failed to allocate memory for video file: %i\n", (uint32_t)size);
m_bitstreamDataSize = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for this code as it hasnt been modified so far

return;
}

m_bitstreamDataSize = size;
fseek(handle, 0, SEEK_SET);
fread(data, 1, size, handle);
m_pBitstreamData = data;
fclose(handle);
#else
std::error_code error;
m_inputVideoStreamMmap.map(pFilePath, 0, mio::map_entire_file, error);
if (error) {
Expand All @@ -46,6 +77,14 @@ class ElementaryStream : public VideoStreamDemuxer {
m_bitstreamDataSize = m_inputVideoStreamMmap.mapped_length();

m_pBitstreamData = m_inputVideoStreamMmap.data();
#endif
if (m_videoCodecType == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
// Assume Duck IVF. DKIF.
assert(*(const uint32_t*)m_pBitstreamData == DKIF_HEADER_MAGIC);
const uint32_t firstFrameOffset = (DKIF_FILE_HEADER_SIZE + DKIF_FRAME_CONTAINER_HEADER_SIZE);
m_pBitstreamData += firstFrameOffset;
m_bitstreamDataSize -= firstFrameOffset;
}
}

ElementaryStream(const uint8_t *pInput, const size_t,
Expand All @@ -54,11 +93,19 @@ class ElementaryStream : public VideoStreamDemuxer {
, m_height(144)
, m_bitDepth(8)
, m_videoCodecType(codecType)
#ifndef USE_SIMPLE_MALLOC
, m_inputVideoStreamMmap()
#endif
, m_pBitstreamData(pInput)
, m_bitstreamDataSize(0)
, m_bytesRead(0) {

, m_bytesRead(0)
{
if (m_videoCodecType == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
// Assume Duck IVF. DKIF.
assert(*(const uint32_t*)pInput == DKIF_HEADER_MAGIC);
const uint32_t firstFrameOffset = (DKIF_FILE_HEADER_SIZE + DKIF_FRAME_CONTAINER_HEADER_SIZE);
m_pBitstreamData += firstFrameOffset;
}
}

int32_t Initialize() { return 0; }
Expand All @@ -83,7 +130,11 @@ class ElementaryStream : public VideoStreamDemuxer {
}

virtual ~ElementaryStream() {
#ifdef USE_SIMPLE_MALLOC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe use #ifndef


#else
m_inputVideoStreamMmap.unmap();
#endif
}

virtual bool IsStreamDemuxerEnabled() const { return false; }
Expand Down Expand Up @@ -135,7 +186,17 @@ class ElementaryStream : public VideoStreamDemuxer {
}
virtual uint32_t GetProfileIdc() const
{
return STD_VIDEO_H264_PROFILE_IDC_MAIN;
switch (m_videoCodecType) {
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
return STD_VIDEO_H264_PROFILE_IDC_MAIN;
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
return STD_VIDEO_H265_PROFILE_IDC_MAIN;
case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
return STD_VIDEO_AV1_PROFILE_MAIN;
default:
assert(0);
}
return (uint32_t)(-1);
}

virtual int32_t GetWidth() const { return m_width; }
Expand All @@ -150,8 +211,18 @@ class ElementaryStream : public VideoStreamDemuxer {
assert(m_pBitstreamData != nullptr);

// Compute and return the pointer to data at new offset.
*ppVideo = (m_pBitstreamData + offset);
return m_bitstreamDataSize - offset;
if (m_videoCodecType == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
*ppVideo = (m_pBitstreamData + offset);
uint32_t dataSize = *(const uint32_t*)(*ppVideo - DKIF_FRAME_CONTAINER_HEADER_SIZE);
if ((m_bitstreamDataSize - (offset + dataSize)) == 0) {
return dataSize;
}

return dataSize + DKIF_FRAME_CONTAINER_HEADER_SIZE;
} else {
*ppVideo = (m_pBitstreamData + offset);
return m_bitstreamDataSize - offset;
}
}

virtual void DumpStreamParameters() const {
Expand All @@ -160,7 +231,9 @@ class ElementaryStream : public VideoStreamDemuxer {
private:
int32_t m_width, m_height, m_bitDepth;
VkVideoCodecOperationFlagBitsKHR m_videoCodecType;
#ifndef USE_SIMPLE_MALLOC
mio::basic_mmap<mio::access_mode::read, uint8_t> m_inputVideoStreamMmap;
#endif
const uint8_t* m_pBitstreamData;
VkDeviceSize m_bitstreamDataSize;
VkDeviceSize m_bytesRead;
Expand Down