From 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d Mon Sep 17 00:00:00 2001 From: Jef Date: Tue, 24 Sep 2024 14:54:57 +0200 Subject: Initial community commit --- Src/Plugins/Input/in_mp4/RawMediaReader.cpp | 145 ++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 Src/Plugins/Input/in_mp4/RawMediaReader.cpp (limited to 'Src/Plugins/Input/in_mp4/RawMediaReader.cpp') diff --git a/Src/Plugins/Input/in_mp4/RawMediaReader.cpp b/Src/Plugins/Input/in_mp4/RawMediaReader.cpp new file mode 100644 index 00000000..4d077a6b --- /dev/null +++ b/Src/Plugins/Input/in_mp4/RawMediaReader.cpp @@ -0,0 +1,145 @@ +#include "RawMediaReader.h" +#include "virtualIO.h" +#include + +bool IsMyExtension(const wchar_t *filename); + +int RawMediaReaderService::CreateRawMediaReader(const wchar_t *filename, ifc_raw_media_reader **out_reader) +{ + if (IsMyExtension(filename)) + { + void *unicode_reader = CreateUnicodeReader(filename); + if (!unicode_reader ) + return NErr_FileNotFound; + + MP4FileHandle mp4 = MP4ReadEx(filename, unicode_reader, &UnicodeIO); + if (!mp4) + { + DestroyUnicodeReader(unicode_reader); + return NErr_Malformed; + } + + + RawMediaReader *reader = new RawMediaReader(mp4, unicode_reader); + if (!reader) + { + MP4Close(mp4); + DestroyUnicodeReader(unicode_reader); + return NErr_OutOfMemory; + } + + *out_reader = reader; + return NErr_Success; + } + else + { + return NErr_False; + } +} + +#define CBCLASS RawMediaReaderService +START_DISPATCH; +CB(CREATERAWMEDIAREADER, CreateRawMediaReader); +END_DISPATCH; +#undef CBCLASS + +RawMediaReader::RawMediaReader(MP4FileHandle file, void *reader) : file(file), reader(reader) +{ + track_num=0; + number_of_tracks=MP4GetNumberOfTracks(file); + current_track = MP4_INVALID_TRACK_ID; + chunk_position=0; + chunk_size=0; + chunk_buffer=0; +} + +RawMediaReader::~RawMediaReader() +{ + if (chunk_buffer) + MP4Free(chunk_buffer); + MP4Close(file); + DestroyUnicodeReader(reader); +} + +int RawMediaReader::ReadNextChunk() +{ +again: + /* see if it's time to cycle to the next track */ + if (current_track == MP4_INVALID_TRACK_ID) + { + if (track_num == number_of_tracks) + return NErr_EndOfFile; + + current_track = MP4FindTrackId(file, track_num); + if (current_track == MP4_INVALID_TRACK_ID) + return NErr_EndOfFile; + + track_num++; + + const char* trackType = MP4GetTrackType(file, current_track); + if (!MP4_IS_AUDIO_TRACK_TYPE(trackType) && !MP4_IS_VIDEO_TRACK_TYPE(trackType)) + { + current_track = MP4_INVALID_TRACK_ID; + goto again; + } + + chunk_id = 1; + number_of_chunks= MP4GetTrackNumberOfChunks(file, current_track); + } + + /* see if we've read all of our samples */ + if (chunk_id > number_of_chunks) + { + current_track = MP4_INVALID_TRACK_ID; + goto again; + } + + bool readSuccess = MP4ReadChunk(file, current_track, chunk_id, &chunk_buffer, &chunk_size); + if (!readSuccess) + return NErr_Error; + + chunk_position=0; + chunk_id++; + return NErr_Success; +} + +int RawMediaReader::Read(void *buffer, size_t buffer_size, size_t *bytes_read) +{ + if (buffer_size > INT_MAX) + return NErr_BadParameter; + + if (chunk_position==chunk_size) + { + MP4Free(chunk_buffer); + chunk_buffer=0; + } + + if (!chunk_buffer) + { + int ret = ReadNextChunk(); + if (ret != NErr_Success) + return ret; + } + + size_t to_read = chunk_size-chunk_position; + if (to_read > buffer_size) + to_read = buffer_size; + + memcpy(buffer, &chunk_buffer[chunk_position], to_read); + chunk_position += to_read; + *bytes_read = to_read; + return NErr_Success; +} + +size_t RawMediaReader::Release() +{ + delete this; + return 0; +} + +#define CBCLASS RawMediaReader +START_DISPATCH; +CB(RELEASE, Release); +CB(RAW_READ, Read); +END_DISPATCH; +#undef CBCLASS \ No newline at end of file -- cgit