-
Notifications
You must be signed in to change notification settings - Fork 4
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
#define USE_SIMPLE_MALLOC 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 { | ||
|
||
|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) { | ||
|
@@ -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, | ||
|
@@ -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; } | ||
|
@@ -83,7 +130,11 @@ class ElementaryStream : public VideoStreamDemuxer { | |
} | ||
|
||
virtual ~ElementaryStream() { | ||
#ifdef USE_SIMPLE_MALLOC | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; } | ||
|
@@ -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; } | ||
|
@@ -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 { | ||
|
@@ -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; | ||
|
There was a problem hiding this comment.
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