aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/mp4
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/replicant/mp4
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/replicant/mp4')
-rw-r--r--Src/replicant/mp4/MP4Decoder.h24
-rw-r--r--Src/replicant/mp4/MP4DecoderCallback.h35
-rw-r--r--Src/replicant/mp4/MP4FileObject.h33
-rw-r--r--Src/replicant/mp4/MP4HTTP.h44
-rw-r--r--Src/replicant/mp4/MP4Metadata.h14
-rw-r--r--Src/replicant/mp4/MP4MetadataBase.h31
-rw-r--r--Src/replicant/mp4/MP4MetadataEditor.h24
-rw-r--r--Src/replicant/mp4/MP4MetadataFile.h15
-rw-r--r--Src/replicant/mp4/MP4MetadataService.h48
-rw-r--r--Src/replicant/mp4/MP4Playback.h39
-rw-r--r--Src/replicant/mp4/MP4PlaybackService.h18
-rw-r--r--Src/replicant/mp4/MP4RawReader.h36
-rw-r--r--Src/replicant/mp4/api.h16
-rw-r--r--Src/replicant/mp4/ifc_mp4audiodecoder.h32
-rw-r--r--Src/replicant/mp4/ifc_mp4file.h72
-rw-r--r--Src/replicant/mp4/main.h18
-rw-r--r--Src/replicant/mp4/precomp.h32
-rw-r--r--Src/replicant/mp4/svc_mp4decoder.h27
18 files changed, 558 insertions, 0 deletions
diff --git a/Src/replicant/mp4/MP4Decoder.h b/Src/replicant/mp4/MP4Decoder.h
new file mode 100644
index 00000000..f7791cb4
--- /dev/null
+++ b/Src/replicant/mp4/MP4Decoder.h
@@ -0,0 +1,24 @@
+//
+// MP4Decoder.h
+//
+// Created by Ben Allison on 1/17/12.
+// Copyright (c) 2012 Nullsoft, Inc. All rights reserved.
+//
+#pragma once
+
+#include "file/svc_filedecode.h"
+#include "nswasabi/ServiceName.h"
+
+// {7EDB2571-AA99-4DF0-8247-A7846B338B04}
+static const GUID mp4_file_decoder_guid =
+{ 0x7edb2571, 0xaa99, 0x4df0, { 0x82, 0x47, 0xa7, 0x84, 0x6b, 0x33, 0x8b, 0x4 } };
+
+class MP4Decoder : public svc_filedecode
+{
+public:
+ WASABI_SERVICE_NAME("MP4 File Decoder");
+ WASABI_SERVICE_GUID(mp4_file_decoder_guid);
+
+private:
+ ns_error_t WASABICALL FileDecodeService_CreateAudioDecoder_Callback(ifc_audio_decoder_callback **decoder, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata, nsaudio::Parameters *parameters, int flags);
+}; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4DecoderCallback.h b/Src/replicant/mp4/MP4DecoderCallback.h
new file mode 100644
index 00000000..7ef992dc
--- /dev/null
+++ b/Src/replicant/mp4/MP4DecoderCallback.h
@@ -0,0 +1,35 @@
+//
+// FLACDecoderPull.h
+// flac
+//
+// Created by Ben Allison on 1/12/12.
+// Copyright (c) 2012 Nullsoft, Inc. All rights reserved.
+//
+#pragma once
+#include "audio/ifc_audio_decoder_callback.h"
+#include "mp4/ifc_mp4audiodecoder.h"
+#include "mp4.h"
+#include "audio/parameters.h"
+#include "MP4FileObject.h"
+#include "nswasabi/MetadataChain.h"
+
+class MP4DecoderCallback : public ifc_audio_decoder_callback
+{
+public:
+ MP4DecoderCallback();
+ ~MP4DecoderCallback();
+ int Initialize(MP4FileHandle mp4_file, ifc_mp4audiodecoder *decoder, int flags, nsaudio::Parameters *parameters, MetadataChain<MP4FileObject> *mp4_file_object);
+
+private:
+ int WASABICALL AudioDecoderCallback_GetMetadata(ifc_metadata **metadata);
+ int WASABICALL AudioDecoderCallback_Decode(ifc_audio_decoder_callback::callback *callback);
+ int WASABICALL AudioDecoderCallback_DecodeStep(ifc_audio_decoder_callback::callback *callback);
+ int WASABICALL AudioDecoderCallback_GetFrameSize(size_t *frame_size);
+ MP4FileHandle mp4_file;
+ ifc_mp4audiodecoder *audio_decoder;
+ MetadataChain<MP4FileObject> *mp4_file_object;
+ int flags;
+ size_t pregap;
+ size_t frame_size;
+ unsigned int channels;
+}; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4FileObject.h b/Src/replicant/mp4/MP4FileObject.h
new file mode 100644
index 00000000..dfc5a934
--- /dev/null
+++ b/Src/replicant/mp4/MP4FileObject.h
@@ -0,0 +1,33 @@
+#pragma once
+#include "ifc_mp4file.h"
+#include "MP4MetadataBase.h"
+#include "mp4.h"
+
+class MP4FileObject : public ifc_mp4file, public MP4MetadataBase
+{
+public:
+ MP4FileObject();
+ ~MP4FileObject();
+ void Initialize(nx_uri_t filename, MP4FileHandle file_handle);
+
+private:
+ MP4FileHandle file_handle;
+
+private:
+ int WASABICALL MP4File_Free(void *buffer);
+
+ int WASABICALL MP4File_Track_GetESConfiguration(TrackID track_number, uint8_t **buffer, uint32_t *buffer_size);
+ int WASABICALL MP4File_Track_GetMaxSampleSize(TrackID track_number, uint32_t *max_sample_size);
+ int WASABICALL MP4File_Track_ConvertFromTimestamp(TrackID track_number, Timestamp timestamp, double *seconds);
+ int WASABICALL MP4File_Track_ConvertToDuration(TrackID track_number, double seconds, Duration *duration);
+ int WASABICALL MP4File_Track_GetMediaDataName(TrackID track_number, const char **name);
+ int WASABICALL MP4File_Track_GetESDSObjectTypeID(TrackID track_number, uint8_t *type);
+ int WASABICALL MP4File_Track_GetAudioMPEG4Type(TrackID track_number, uint8_t *type);
+ int WASABICALL MP4File_Track_GetBytesProperty(TrackID track_number, const char *property_name, uint8_t **buffer, uint32_t *buffer_size);
+
+ int WASABICALL MP4File_Metadata_iTunes_FindFreeform(const char *name, const char *mean, metadata_itunes_atom_t *atom);
+ int WASABICALL MP4File_Metadata_iTunes_GetBinary(metadata_itunes_atom_t atom, const uint8_t **value, size_t *value_length);
+
+ int WASABICALL MP4File_Sample_Read(TrackID track_number, SampleID sample_number, uint8_t **bytes, uint32_t *bytes_length, Timestamp *start_time, Duration *duration, Duration *offset, int *is_sync);
+ int WASABICALL MP4File_Sample_GetFromDuration(TrackID track_number, Duration duration, SampleID *sample_id);
+}; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4HTTP.h b/Src/replicant/mp4/MP4HTTP.h
new file mode 100644
index 00000000..5580d3f4
--- /dev/null
+++ b/Src/replicant/mp4/MP4HTTP.h
@@ -0,0 +1,44 @@
+#pragma once
+#include "http/svc_http_demuxer.h"
+#include "http/ifc_http_demuxer.h"
+#include "nx/nxstring.h"
+#include "nswasabi/ServiceName.h"
+#include "MP4FileObject.h"
+#include "ifc_mp4audiodecoder.h"
+
+// {C67A19EF-CBDB-4BD9-9B4F-EEC5D6B05093}
+static const GUID mp4_demuxer_guid =
+{ 0xc67a19ef, 0xcbdb, 0x4bd9, { 0x9b, 0x4f, 0xee, 0xc5, 0xd6, 0xb0, 0x50, 0x93 } };
+
+
+class MP4HTTPService : public svc_http_demuxer
+{
+public:
+ WASABI_SERVICE_NAME("MP4 HTTP Demuxer");
+ static GUID GetServiceGUID() { return mp4_demuxer_guid; }
+
+ const char *WASABICALL HTTPDemuxerService_EnumerateAcceptedTypes(size_t i);
+ const char *WASABICALL HTTPDemuxerService_GetUserAgent();
+ void WASABICALL HTTPDemuxerService_CustomizeHTTP(jnl_http_t http);
+ NError WASABICALL HTTPDemuxerService_CreateDemuxer(nx_uri_t uri, jnl_http_t http, ifc_http_demuxer **demuxer, int pass);
+};
+
+class MP4HTTP : public ifc_http_demuxer
+{
+public:
+ MP4HTTP();
+ ~MP4HTTP();
+
+ int Initialize(nx_uri_t uri, jnl_http_t http);
+private:
+ /* ifc_http_demuxer implementation */
+ int WASABICALL HTTPDemuxer_Run(ifc_http *http_parent, ifc_player *player, ifc_playback_parameters *secondary_parameters);
+
+ /* member data */
+ jnl_http_t http;
+ nx_uri_t uri;
+ nx_file_t file;
+ MP4FileObject *mp4_file_object;
+ ifc_audioout::Parameters audio_parameters;
+ ifc_mp4audiodecoder *audio_decoder;
+};
diff --git a/Src/replicant/mp4/MP4Metadata.h b/Src/replicant/mp4/MP4Metadata.h
new file mode 100644
index 00000000..003826f7
--- /dev/null
+++ b/Src/replicant/mp4/MP4Metadata.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "MP4MetadataBase.h"
+#include "nx/nxuri.h"
+
+ class MP4Metadata : public MP4MetadataBase
+ {
+ public:
+ MP4Metadata();
+ ~MP4Metadata();
+ int Initialize(nx_uri_t filename);
+
+ private:
+ MP4FileHandle mp4_file;
+ }; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4MetadataBase.h b/Src/replicant/mp4/MP4MetadataBase.h
new file mode 100644
index 00000000..ba90692c
--- /dev/null
+++ b/Src/replicant/mp4/MP4MetadataBase.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "metadata/ifc_metadata.h"
+#include "mp4.h"
+
+class MP4MetadataBase : public ifc_metadata
+{
+public:
+ MP4MetadataBase();
+ ~MP4MetadataBase();
+ int Initialize(nx_uri_t filename, MP4FileHandle mp4_file);
+
+ int WASABICALL Metadata_GetField(int field, unsigned int index, nx_string_t *value);
+ int WASABICALL Metadata_GetInteger(int field, unsigned int index, int64_t *value);
+ int WASABICALL Metadata_GetReal(int field, unsigned int index, double *value);
+ int WASABICALL Metadata_GetArtwork(int field, unsigned int index, artwork_t *artwork, data_flags_t flags);
+ int WASABICALL Metadata_GetBinary(int field, unsigned int index, nx_data_t *data) { return NErr_NotImplemented; }
+private:
+ MP4FileHandle mp4_file;
+ nx_uri_t mp4_metadata_filename;
+ nx_file_stat_s file_stats;
+ static struct mime_types_t
+ {
+ nx_string_t jpeg;
+ nx_string_t png;
+ nx_string_t bmp;
+ nx_string_t gif;
+ } mime_types;
+ static int NX_ONCE_API InitMIME(nx_once_t, void *, void **);
+ static nx_string_t GetMIMEFromType(uint32_t type);
+}; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4MetadataEditor.h b/Src/replicant/mp4/MP4MetadataEditor.h
new file mode 100644
index 00000000..038a1904
--- /dev/null
+++ b/Src/replicant/mp4/MP4MetadataEditor.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "mp4.h"
+#include "metadata/ifc_metadata_editor.h"
+#include "nx/nxuri.h"
+
+class MP4MetadataEditor : public ifc_metadata_editor
+{
+public:
+ MP4MetadataEditor();
+ ~MP4MetadataEditor();
+ int Initialize(nx_uri_t filename);
+
+private:
+ MP4FileHandle mp4_file;
+
+ int WASABICALL MetadataEditor_Save();
+
+ int WASABICALL MetadataEditor_SetField(int field, unsigned int index, nx_string_t value);
+ int WASABICALL MetadataEditor_SetInteger(int field, unsigned int index, int64_t value);
+ int WASABICALL MetadataEditor_SetReal(int field, unsigned int index, double value);
+
+ int WASABICALL MetadataEditor_SetArtwork(int field, unsigned int index, artwork_t *artwork, data_flags_t flags);
+ nx_uri_t filename;
+}; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4MetadataFile.h b/Src/replicant/mp4/MP4MetadataFile.h
new file mode 100644
index 00000000..93aedc98
--- /dev/null
+++ b/Src/replicant/mp4/MP4MetadataFile.h
@@ -0,0 +1,15 @@
+#pragma once
+#include "MP4MetadataBase.h"
+#include "nx/nxuri.h"
+#include "nx/nxfile.h"
+
+ class MP4MetadataFile : public MP4MetadataBase
+ {
+ public:
+ MP4MetadataFile();
+ ~MP4MetadataFile();
+ int Initialize(nx_uri_t filename, nx_file_t file);
+
+ private:
+ MP4FileHandle mp4_file;
+ }; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4MetadataService.h b/Src/replicant/mp4/MP4MetadataService.h
new file mode 100644
index 00000000..f864400c
--- /dev/null
+++ b/Src/replicant/mp4/MP4MetadataService.h
@@ -0,0 +1,48 @@
+#pragma once
+#include "metadata/svc_metadata.h"
+#include "file/svc_filemetadata.h"
+#include "nswasabi/ServiceName.h"
+#include "MP4MetadataFile.h"
+#include "nswasabi/MetadataChain.h"
+#include "nx/nxonce.h"
+
+// {71102FF2-D9CF-4a0e-9C83-858E80B65DD4}
+static const GUID mp4_metadata_guid =
+{ 0x71102ff2, 0xd9cf, 0x4a0e, { 0x9c, 0x83, 0x85, 0x8e, 0x80, 0xb6, 0x5d, 0xd4 } };
+
+
+class MP4MetadataService : public svc_metadata
+{
+public:
+ WASABI_SERVICE_NAME("MP4 Metadata");
+ WASABI_SERVICE_GUID(mp4_metadata_guid);
+ MP4MetadataService();
+ static nx_once_value_t mime_once;
+private:
+ int WASABICALL MetadataService_EnumerateExtensions(unsigned int index, nx_string_t *extension);
+ int WASABICALL MetadataService_CreateMetadata(unsigned int pass, nx_uri_t filename, ifc_metadata **metadata);
+ int WASABICALL MetadataService_CreateMetadataEditor(unsigned int pass, nx_uri_t filename, ifc_metadata_editor **metadata);
+};
+
+// {F3AD1E12-345C-4E00-83C1-4DAB2D88BF4F}
+static const GUID mp4_file_metadata_guid =
+{ 0xf3ad1e12, 0x345c, 0x4e00, { 0x83, 0xc1, 0x4d, 0xab, 0x2d, 0x88, 0xbf, 0x4f } };
+
+class MP4FileMetadataService : public svc_filemetadata
+{
+public:
+ WASABI_SERVICE_NAME("MP4 File Metadata");
+ WASABI_SERVICE_GUID(mp4_file_metadata_guid);
+private:
+ int WASABICALL FileMetadataService_EnumerateExtensions(unsigned int index, nx_string_t *extension);
+ int WASABICALL FileMetadataService_CreateFileMetadata(ifc_metadata **file_metadata, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata);
+};
+
+class MP4FileMetadata : public MetadataChain<MP4MetadataFile>
+{
+public:
+ MP4FileMetadata();
+ ~MP4FileMetadata();
+ ns_error_t Initialize(nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata);
+
+}; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4Playback.h b/Src/replicant/mp4/MP4Playback.h
new file mode 100644
index 00000000..ca6956ef
--- /dev/null
+++ b/Src/replicant/mp4/MP4Playback.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "mp4.h"
+#include "file/ifc_fileplayback.h"
+#include "mp4/ifc_mp4audiodecoder.h"
+#include "MP4MetadataBase.h"
+#include "MP4FileObject.h"
+#include "nswasabi/MetadataChain.h"
+
+class MP4Playback : public ifc_fileplayback
+{
+public:
+ MP4Playback();
+ ~MP4Playback();
+
+ int Initialize(nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata, ifc_fileplayback_parent *parent);
+private:
+ ifc_mp4audiodecoder *audio_decoder;
+ MP4FileHandle mp4_file;
+ ifc_audioout::Parameters audio_parameters;
+ MetadataChain<MP4FileObject> *mp4_file_object;
+ bool output_opened;
+ double samples_per_second;
+ nx_file_t file;
+ ifc_fileplayback_parent *parent;
+ nx_uri_t filename;
+private:
+ int Init(nx_file_t file, ifc_metadata *parent_metadata);
+ int Configure();
+
+ void WASABICALL FilePlayback_Close();
+ ns_error_t WASABICALL FilePlayback_Seekable();
+ ns_error_t WASABICALL FilePlayback_GetMetadata(ifc_metadata **metadata);
+ ns_error_t WASABICALL FilePlayback_GetLength(double *length, ns_error_t *exact);
+ ns_error_t WASABICALL FilePlayback_GetBitrate(double *bitrate, ns_error_t *exact);
+ ns_error_t WASABICALL FilePlayback_Seek(const Agave_Seek *seek, ns_error_t *seek_error, double *new_position);
+ ns_error_t WASABICALL FilePlayback_DecodeStep();
+ ns_error_t WASABICALL FilePlayback_Interrupt(Agave_Seek *resume_information);
+ ns_error_t WASABICALL FilePlayback_Resume(Agave_Seek *resume_information, nx_file_t file, ifc_metadata *parent_metadata);
+}; \ No newline at end of file
diff --git a/Src/replicant/mp4/MP4PlaybackService.h b/Src/replicant/mp4/MP4PlaybackService.h
new file mode 100644
index 00000000..bfef5a88
--- /dev/null
+++ b/Src/replicant/mp4/MP4PlaybackService.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "file/svc_fileplayback.h"
+#include "nx/nxstring.h"
+#include "nswasabi/ServiceName.h"
+
+// {AA80A650-FC61-4011-BB17-E4EBA5C185D9}
+static const GUID mp4_file_playback_guid =
+{ 0xaa80a650, 0xfc61, 0x4011, { 0xbb, 0x17, 0xe4, 0xeb, 0xa5, 0xc1, 0x85, 0xd9 } };
+
+
+class MP4PlaybackService : public svc_fileplayback
+{
+public:
+ WASABI_SERVICE_NAME("MP4 File Playback Service");
+ WASABI_SERVICE_GUID(mp4_file_playback_guid);
+
+ ns_error_t WASABICALL FilePlaybackService_CreatePlayback(ifc_fileplayback **out_playback_object, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata, ifc_fileplayback_parent *parent);
+};
diff --git a/Src/replicant/mp4/MP4RawReader.h b/Src/replicant/mp4/MP4RawReader.h
new file mode 100644
index 00000000..8d1547b4
--- /dev/null
+++ b/Src/replicant/mp4/MP4RawReader.h
@@ -0,0 +1,36 @@
+#pragma once
+#include "file/svc_filerawreader.h"
+#include "decode/ifc_raw_media_reader.h"
+#include "mp4.h"
+#include "nswasabi/ServiceName.h"
+
+// {5CBD1F27-5A63-4D8C-9297-D74518E1EF3A}
+static const GUID mp4_raw_reader_guid =
+{ 0x5cbd1f27, 0x5a63, 0x4d8c, { 0x92, 0x97, 0xd7, 0x45, 0x18, 0xe1, 0xef, 0x3a } };
+
+class MP4RawReaderService : public svc_filerawreader
+{
+public:
+ WASABI_SERVICE_NAME("MP4 Raw Reader");
+ static GUID GetServiceGUID() { return mp4_raw_reader_guid; }
+ ns_error_t WASABICALL FileRawReaderService_CreateRawMediaReader(ifc_raw_media_reader **reader, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata);
+};
+
+class MP4RawReader : public ifc_raw_media_reader
+{
+public:
+ MP4RawReader();
+ ~MP4RawReader();
+ int Initialize(MP4FileHandle file);
+ int WASABICALL RawMediaReader_Read(void *buffer, size_t buffer_size, size_t *bytes_read);
+private:
+ uint16_t track_num;
+ uint32_t number_of_tracks;
+ MP4TrackId current_track;
+ MP4FileHandle file;
+ MP4ChunkId chunk_id;
+ MP4ChunkId number_of_chunks;
+ uint32_t chunk_position, chunk_size;
+ uint8_t *chunk_buffer;
+ int ReadNextChunk();
+}; \ No newline at end of file
diff --git a/Src/replicant/mp4/api.h b/Src/replicant/mp4/api.h
new file mode 100644
index 00000000..24e247ab
--- /dev/null
+++ b/Src/replicant/mp4/api.h
@@ -0,0 +1,16 @@
+#pragma once
+#include "service/api_service.h"
+extern api_service *serviceManager;
+#define WASABI2_API_SVC serviceManager
+
+#include "application/api_application.h"
+extern api_application *applicationApi;
+#define WASABI2_API_APP applicationApi
+
+#include "metadata/api_metadata.h"
+extern api_metadata *metadata_api;
+#define REPLICANT_API_METADATA metadata_api
+
+#include "filelock/api_filelock.h"
+extern api_filelock *filelock_api;
+#define REPLICANT_API_FILELOCK filelock_api \ No newline at end of file
diff --git a/Src/replicant/mp4/ifc_mp4audiodecoder.h b/Src/replicant/mp4/ifc_mp4audiodecoder.h
new file mode 100644
index 00000000..7c1ffa65
--- /dev/null
+++ b/Src/replicant/mp4/ifc_mp4audiodecoder.h
@@ -0,0 +1,32 @@
+#pragma once
+#include "foundation/dispatch.h"
+#include "ifc_mp4file.h"
+#include "audio/ifc_audioout.h"
+
+class ifc_mp4audiodecoder : public Wasabi2::Dispatchable
+{
+ protected:
+ ifc_mp4audiodecoder() : Dispatchable(DISPATCHABLE_VERSION) {}
+ ~ifc_mp4audiodecoder() {}
+public:
+ int FillAudioParameters(ifc_audioout::Parameters *parameters) { return MP4AudioDecoder_FillAudioParameters(parameters); }
+ int Decode(const void **output_buffer, size_t *output_buffer_bytes, double *start_position, double *end_position) { return MP4AudioDecoder_Decode(output_buffer, output_buffer_bytes, start_position, end_position); }
+ int Seek(ifc_mp4file::SampleID sample_number) { return MP4AudioDecoder_Seek(sample_number); }
+ int SeekSeconds(double *seconds) { return MP4AudioDecoder_SeekSeconds(seconds); }
+ int ConnectFile(ifc_mp4file *new_file) { return MP4AudioDecoder_ConnectFile(new_file); }
+
+ enum
+ {
+ DISPATCHABLE_VERSION,
+ };
+private:
+ /* sizeof_parameters will already be filled out for you */
+ virtual int WASABICALL MP4AudioDecoder_FillAudioParameters(ifc_audioout::Parameters *parameters)=0;
+ virtual int WASABICALL MP4AudioDecoder_Decode(const void **output_buffer, size_t *output_buffer_bytes, double *start_position, double *end_position)=0;
+ virtual int WASABICALL MP4AudioDecoder_Seek(ifc_mp4file::SampleID sample_number) = 0;
+ /* fill in with the actual seconds you'll resume playback at */
+ virtual int WASABICALL MP4AudioDecoder_SeekSeconds(double *seconds) = 0;
+ /* this is an unfortunate wart in the API. In order to support editing metadata on an actively playing file, we have to re-open the file which will generate a new ifc_mp4file object.
+ do _not_ reset the decoder or change the sample number. You should assume the file is identical from a playback point-of-view, just release your old object and retain/assign the new one */
+ virtual int WASABICALL MP4AudioDecoder_ConnectFile(ifc_mp4file *new_file)=0;
+};
diff --git a/Src/replicant/mp4/ifc_mp4file.h b/Src/replicant/mp4/ifc_mp4file.h
new file mode 100644
index 00000000..310811d3
--- /dev/null
+++ b/Src/replicant/mp4/ifc_mp4file.h
@@ -0,0 +1,72 @@
+#pragma once
+#include "foundation/dispatch.h"
+
+static const uint32_t mp4file_invalid_track_id=0;
+
+class ifc_mp4file : public Wasabi2::Dispatchable
+{
+ protected:
+ ifc_mp4file() : Dispatchable(DISPATCHABLE_VERSION) {}
+ ~ifc_mp4file() {}
+public:
+ typedef uint32_t TrackID;
+ typedef uint32_t SampleID;
+ typedef uint64_t Timestamp;
+ typedef uint64_t Duration;
+ typedef struct metadata_itunes_atom_s {} *metadata_itunes_atom_t;
+
+ int Free(void *buffer) { return MP4File_Free(buffer); }
+
+ int Track_GetESConfiguration(TrackID track_number, uint8_t **buffer, uint32_t *buffer_size) { return MP4File_Track_GetESConfiguration(track_number, buffer, buffer_size); }
+ int Track_GetMaxSampleSize(TrackID track_number, uint32_t *max_sample_size) { return MP4File_Track_GetMaxSampleSize(track_number, max_sample_size); }
+ int Track_ConvertFromTimestamp(TrackID track_number, Timestamp timestamp, double *seconds) { return MP4File_Track_ConvertFromTimestamp(track_number, timestamp, seconds); }
+ int Track_ConvertToDuration(TrackID track_number, double seconds, Duration *duration) { return MP4File_Track_ConvertToDuration(track_number, seconds, duration); }
+ int Track_GetMediaDataName(TrackID track_number, const char **name) { return MP4File_Track_GetMediaDataName(track_number, name); }
+ int Track_GetESDSObjectTypeID(TrackID track_number, uint8_t *type) { return MP4File_Track_GetESDSObjectTypeID(track_number, type); }
+ int Track_GetAudioMPEG4Type(TrackID track_number, uint8_t *type) { return MP4File_Track_GetAudioMPEG4Type(track_number, type); }
+ int Track_GetBytesProperty(TrackID track_number, const char *property_name, uint8_t **buffer, uint32_t *buffer_size) { return MP4File_Track_GetBytesProperty(track_number, property_name, buffer, buffer_size); }
+
+ int Metadata_iTunes_FindFreeform(const char *name, const char *mean, metadata_itunes_atom_t *atom) { return MP4File_Metadata_iTunes_FindFreeform(name, mean, atom); }
+ int Metadata_iTunes_GetBinary(metadata_itunes_atom_t atom, const uint8_t **value, size_t *value_length) { return MP4File_Metadata_iTunes_GetBinary(atom, value, value_length); }
+
+ int Sample_Read(TrackID track_number, SampleID sample_number, uint8_t **bytes, uint32_t *bytes_length, Timestamp *start_time=0, Duration *duration=0, Duration *offset=0, int *is_sync=0) { return MP4File_Sample_Read(track_number, sample_number, bytes, bytes_length, start_time, duration, offset, is_sync); }
+ int Sample_GetFromDuration(TrackID track_number, Duration duration, SampleID *sample_id) { return MP4File_Sample_GetFromDuration(track_number, duration, sample_id); }
+
+
+ enum
+ {
+ esds_object_type_mpeg4_audio = 0x40,
+ esds_object_type_mpeg2_aac_lc_audio = 0x67,
+ esds_object_type_mpeg2_audio = 0x69,
+ esds_object_type_mpeg1_audio = 0x6B,
+
+ mpeg4_audio_type_aac_lc = 2,
+ mpeg4_audio_type_he_aac = 5,
+ mpeg4_audio_type_layer1 = 32,
+ mpeg4_audio_type_layer2 = 33,
+ mpeg4_audio_type_layer3 = 34,
+ };
+
+ enum
+ {
+ DISPATCHABLE_VERSION,
+ };
+private:
+ virtual int WASABICALL MP4File_Free(void *buffer)=0;
+
+ virtual int WASABICALL MP4File_Track_GetESConfiguration(TrackID track_number, uint8_t **buffer, uint32_t *buffer_size)=0;
+ virtual int WASABICALL MP4File_Track_GetMaxSampleSize(TrackID track_number, uint32_t *max_sample_size)=0;
+ virtual int WASABICALL MP4File_Track_ConvertFromTimestamp(TrackID track_number, Timestamp timestamp, double *seconds)=0;
+ virtual int WASABICALL MP4File_Track_ConvertToDuration(TrackID track_number, double seconds, Duration *duration)=0;
+ virtual int WASABICALL MP4File_Track_GetMediaDataName(TrackID track_number, const char **name)=0;
+ virtual int WASABICALL MP4File_Track_GetESDSObjectTypeID(TrackID track_number, uint8_t *type)=0;
+ virtual int WASABICALL MP4File_Track_GetAudioMPEG4Type(TrackID track_number, uint8_t *type)=0;
+ virtual int WASABICALL MP4File_Track_GetBytesProperty(TrackID track_number, const char *property_name, uint8_t **buffer, uint32_t *buffer_size)=0;
+
+ virtual int WASABICALL MP4File_Metadata_iTunes_FindFreeform(const char *name, const char *mean, metadata_itunes_atom_t *atom)=0;
+ virtual int WASABICALL MP4File_Metadata_iTunes_GetBinary(metadata_itunes_atom_t atom, const uint8_t **value, size_t *value_length)=0;
+
+ virtual int WASABICALL MP4File_Sample_Read(TrackID track_number, SampleID sample_number, uint8_t **bytes, uint32_t *bytes_length, Timestamp *start_time, Duration *duration, Duration *offset, int *is_sync)=0;
+ virtual int WASABICALL MP4File_Sample_GetFromDuration(TrackID track_number, Duration duration, SampleID *sample_id)=0;
+
+};
diff --git a/Src/replicant/mp4/main.h b/Src/replicant/mp4/main.h
new file mode 100644
index 00000000..b997a277
--- /dev/null
+++ b/Src/replicant/mp4/main.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "nx/nxuri.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ enum
+ {
+ EXTENSION_FOR_PLAYBACK,
+ EXTENSION_FOR_METADATA,
+ EXTENSION_FOR_AUDIO_DECODE,
+ };
+ bool IsMyExtension(nx_uri_t filename, int search_style);
+ int EnumerateExtensions(unsigned int index, nx_string_t *extension, int search_style);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/Src/replicant/mp4/precomp.h b/Src/replicant/mp4/precomp.h
new file mode 100644
index 00000000..4a141102
--- /dev/null
+++ b/Src/replicant/mp4/precomp.h
@@ -0,0 +1,32 @@
+//
+// precomp.h
+// mp4
+//
+
+#include <assert.h>
+
+#ifdef __cplusplus
+#include "new"
+#endif
+
+#include "foundation/error.h"
+#include "foundation/types.h"
+
+#include "nu/ByteReader.h"
+#include "nu/ByteWriter.h"
+#include "nu/strsafe.h"
+
+#include "nx/nx.h"
+
+#ifdef __cplusplus
+#include "mp4.h"
+#include "nsmp4.h"
+#include "nu/PtrDeque.h"
+#include "jnetlib/jnetlib.h"
+#include "nswasabi/ReferenceCounted.h"
+#include "nswasabi/ServiceName.h"
+#include "decode/svc_decode.h"
+#include "http/svc_http_demuxer.h"
+#include "replaygain/ifc_replaygain_settings.h"
+#include "service/ifc_servicefactory.h"
+#endif \ No newline at end of file
diff --git a/Src/replicant/mp4/svc_mp4decoder.h b/Src/replicant/mp4/svc_mp4decoder.h
new file mode 100644
index 00000000..d8e242ad
--- /dev/null
+++ b/Src/replicant/mp4/svc_mp4decoder.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "foundation/dispatch.h"
+#include "ifc_mp4file.h"
+
+class ifc_mp4audiodecoder;
+class ifc_mp4videodecoder;
+
+// {39A53910-CCFE-465D-A46C-F0B95C7DD257}
+static const GUID mp4_decoder_service_type_guid =
+{ 0x39a53910, 0xccfe, 0x465d, { 0xa4, 0x6c, 0xf0, 0xb9, 0x5c, 0x7d, 0xd2, 0x57 } };
+
+class svc_mp4decoder : public Wasabi2::Dispatchable
+{
+protected:
+ svc_mp4decoder() : Dispatchable(DISPATCHABLE_VERSION) {}
+ ~svc_mp4decoder() {}
+public:
+ static GUID GetServiceType() { return mp4_decoder_service_type_guid; }
+ int CreateAudioDecoder(ifc_mp4file *mp4_file, ifc_mp4file::TrackID mp4_track, ifc_mp4audiodecoder **decoder) { return MP4DecoderService_CreateAudioDecoder(mp4_file, mp4_track, decoder); }
+
+ enum
+ {
+ DISPATCHABLE_VERSION=0,
+ };
+private:
+ virtual int WASABICALL MP4DecoderService_CreateAudioDecoder(ifc_mp4file *mp4_file, ifc_mp4file::TrackID mp4_track, ifc_mp4audiodecoder **decoder)=0;
+};