public:
FileMatroska(IOCallback & output);
~FileMatroska() = default;
-#ifdef OLD
- filepos_t RenderHead(const std::string & aEncoderApp);
- std::uint32_t ReadHead();
- std::uint32_t ReadTracks();
- std::uint32_t ReadCodec();
- void Close(const std::uint32_t aTimeLength);
-
- inline void type_SetInfo(const std::string & aStr) {myMainHeader.type_SetInfo(aStr);}
- inline void type_SetAds(const std::string & aStr) {myMainHeader.type_SetAds(aStr);}
- inline void type_SetSize(const std::string & aStr) {myMainHeader.type_SetSize(aStr);}
- inline void type_SetSize(std::uint64_t aSize) {myMainHeader.type_SetSize(aSize);}
-
- inline std::uint8_t GetTrackNumber() const { return myTracks.size(); }
-
- void track_SetName(Track * aTrack, const std::string & aName);
- void track_SetLaced(Track * aTrack, bool bLaced = true);
-
- Track * CreateTrack(const track_type aType);
- inline Track * GetTrack(const std::uint8_t aTrackNb) const
- {
- if (aTrackNb > myTracks.size())
- return NULL;
- else
- return myTracks[aTrackNb-1];
- }
-
- void Track_GetInfo(const Track * aTrack, TrackInfo & aTrackInfo) const;
-
- void Track_SetInfo_Audio(Track * aTrack, const TrackInfoAudio & aTrackInfo);
- void Track_GetInfo_Audio(const Track * aTrack, TrackInfoAudio & aTrackInfo) const;
-
- void Track_SetInfo_Video(Track * aTrack, const TrackInfoVideo & aTrackInfo);
- void Track_GetInfo_Video(const Track * aTrack, TrackInfoVideo & aTrackInfo) const;
-
- void SelectReadingTrack(Track * aTrack, bool select = true);
-
- /*!
- \return wether the frame has been added or not
- */
- bool AddFrame(Track * aTrack, const std::uint32_t aTimecode, const binary *aFrame, const std::uint32_t aFrameSize,
- bool aKeyFrame = true, bool aBFrame = false);
-
- /*!
- \return wether the frame has been read or not
- */
- bool ReadFrame(Track * & aTrack, std::uint32_t & aTimecode, const binary * & aFrame, std::uint32_t & aFrameSize,
- bool & aKeyFrame, bool & aBFrame);
-
- /*
- Render the pending cluster to file
- */
- void Flush();
-
- void SetMaxClusterSize(const std::uint32_t value);
- void SetMinClusterSize(const std::uint32_t value) {myMinClusterSize = value;}
-
- protected:
- MainHeader myMainHeader;
-
- std::vector<Track *> myTracks;
- std::vector<std::uint8_t> mySelectedTracks;
-
-// Track *findTrack(Track * aTrack) const;
-
- Cluster myCurrWriteCluster; /// \todo merge with the write one ?
- std::uint32_t myReadBlockNumber;
- Cluster myCurrReadCluster;
- binary * myCurrReadBlock; ///< The buffer containing the current read block
- std::uint32_t myCurrReadBlockSize; ///< The size of the buffer containing the current read block
- std::uint8_t myCurrReadBlockTrack; ///< The track number of the current track to read
-
- std::uint32_t myMaxClusterSize;
- std::uint32_t myMinClusterSize;
-
- StreamInfo myStreamInfo;
-
- CodecHeader myCodecHeader;
-
- inline bool IsMyTrack(const Track * aTrack) const;
- inline bool IsReadingTrack(const std::uint8_t aTrackNum) const;
-#endif // OLD
- IOCallback & myFile;
+ IOCallback & myFile;
};
extern "C" {
#endif
-#ifdef OLD
-
-/*!
- \fn int matroska_plug_log(matroska_error_callback)
- \brief Attach a callback to be informed when error occurs
- \param callback The callback that will be called when logging occurs \return 0 if successfull
-*/
-int matroska_plug_log(matroska_error_callback callback);
-
-/*!
- \fn int matroska_unplug_log(matroska_error_callback)
- \brief Unattach an attached callback to be informed when error occurs
- \param callback The callback that was called when logging occurs \return 0 if successfull
-*/
-int matroska_unplug_log(matroska_error_callback callback);
-
-/*!
- \fn matroska_id matroska_open_file(c_string,matroska_file_mode)
- \brief Open an instance of an Matroska file
- \param string The name of the file to open (including OS depedant path) \param mode The mode to open the file (read, write, etc)
- \return NULL if the opening failed or an ID that will be used to access this file from the API
-*/
-matroska_stream MATROSKA_EXPORT matroska_open_stream_file(c_string string, open_mode mode);
-
-matroska_id MATROSKA_EXPORT matroska_open_stream(matroska_stream a_stream);
-
-/*!
- \fn matroska_id matroska_open_url(c_string)
- \brief Open an instance of an Matroska file from a URL
- \param string The name of the URL to open \return NULL if the opening failed or an ID that will be used to access this file from the API
- \warning Open only for reading ?
- \note It requires that Curl is compiled or installed
-*/
-matroska_id matroska_open_url(c_string string);
-
-/*!
- \fn int matroska_close(matroska_id)
- \brief Close the specified Matroska instance
- \param id The instance to close \return 0 if successfull
-*/
-void MATROSKA_EXPORT matroska_close(matroska_id id);
-
-void MATROSKA_EXPORT matroska_end(matroska_id id, std::uint32_t totaltime);
-
-matroska_track MATROSKA_EXPORT matroska_create_track(matroska_id id, enum track_type type);
-
-void MATROSKA_EXPORT matroska_read_head(matroska_id id);
-void MATROSKA_EXPORT matroska_read_tracks(matroska_id id);
-
-std::uint8_t MATROSKA_EXPORT matroska_get_number_track(matroska_id id);
-
-matroska_track MATROSKA_EXPORT matroska_get_track(matroska_id id, std::uint8_t track_index);
-
-void MATROSKA_EXPORT matroska_get_track_info(matroska_id id, matroska_track track, track_info * infos);
-
-/*
-int matroska_track_write_block(matroska_track, void* buffer, unsigned int size);
-int matroska_track_close(matroska_track);
-*/
-
-#endif /* OLD */
-
#ifdef __cplusplus
}
#endif
FileMatroska::FileMatroska(IOCallback & output)
:myFile(output)
-#ifdef OLD
- ,myCurrReadBlock(NULL)
- ,myMinClusterSize(5*1024) // 5KB is the min size of a cluster
- ,myMaxClusterSize(2*1024*1024) // 2MB is the max size of a cluster
- ,myCurrReadBlockTrack(0)
- ,myCurrWriteCluster(2*1024*1024) // myMaxClusterSize
- ,myCurrReadCluster(NULL)
- ,myReadBlockNumber(0)
-#endif // OLD
{
-#ifdef OLD
- myStreamInfo.MainHeaderSize = TypeHeader::default_size() +
- ActualHeader::default_size() +
- ExtendedInfo::default_size() +
- ContentInfo::default_size();
- myStreamInfo.TrackEntrySize = Track::default_size();
- myStreamInfo.BlockHeadSize = BLOCK_HEADER_SIZE;
- myStreamInfo.ClusterHeadSize = CLUSTER_HEADER_SIZE;
- myStreamInfo.ClusterFootSize = CLUSTER_TRAILER_SIZE;
-#endif // OLD
}
/* FileMatroska::~FileMatroska()
// throw 0; // there are some data left to write
} */
-#ifdef OLD
-void FileMatroska::SetMaxClusterSize(const std::uint32_t value)
-{
- myMaxClusterSize = value;
- myCurrWriteCluster.setMaxSize(value);
-}
-
-void FileMatroska::Close(const std::uint32_t aTimeLength)
-{
- Flush();
-
- // get the file size
- myFile.setFilePointer(0,seek_end);
- myMainHeader.type_SetSize(myFile.getFilePointer());
-
- // rewrite the header at the beginning
- myFile.setFilePointer(0,seek_beginning);
-
- // get the Track-entry size
- std::uint32_t track_entries_size = 0;
- for (const auto& myTrack : myTracks) {
- track_entries_size += myTrack->default_size();
- }
-
- myStreamInfo.TrackEntriesSize = track_entries_size;
- myStreamInfo.TimeLength = aTimeLength;
- myMainHeader.Render(myFile, myStreamInfo);
-
- for (auto& track : myTracks) {
- delete track;
- }
-}
-
-/*!
- \warning after rendering the head, some parameters are locked
-*/
-filepos_t FileMatroska::RenderHead(const std::string & aEncoderApp)
-{
- try {
- std::uint32_t track_entries_size = 0;
- for (const auto& myTrack : myTracks) {
- track_entries_size += myTrack->default_size();
- }
-
- std::string aStr = LIB_NAME;
- aStr += " ";
- aStr += VERSION;
- myStreamInfo.EncoderLib = aStr;
-
- myStreamInfo.EncoderApp = aEncoderApp;
-
- myStreamInfo.TrackEntryPosition = 0 + myStreamInfo.MainHeaderSize;
- myStreamInfo.TrackEntriesSize = myTracks.size() * myStreamInfo.TrackEntrySize;
-
- myStreamInfo.CodecEntryPosition = myStreamInfo.MainHeaderSize + myStreamInfo.TrackEntriesSize;
- myStreamInfo.CodecEntrySize = 4;
- for (const auto& myTrack : myTracks) {
- myStreamInfo.CodecEntrySize += myTrack->CodecSize();
- }
-
- // Main Header
- filepos_t result = myMainHeader.Render(myFile, myStreamInfo);
-
- // Track Entries
- for (i=0; i<myTracks.size(); i++) {
- myTracks[i]->RenderEntry(myFile, i+1);
- }
- myStreamInfo.ClusterPosition = myStreamInfo.CodecEntryPosition + myStreamInfo.CodecEntrySize;
-
- // Codec Header
- result = CodecHeader::Render(myFile, myTracks);
-
- return result;
- }
- catch (exception & Ex) {
- throw Ex;
- }
-}
-
-/*!
- \return 0 if the track was not created, or a valid track number
-*/
-Track * FileMatroska::CreateTrack(const track_type aType)
-{
- myTracks.emplace_back(aType);
- return myTracks.back();
-}
-
-/*Track *FileMatroska::findTrack(Track * aTrack) const {
- for (std::size_t i=0; i<myTracks.size(); i++) {
- if (myTracks[i] == aTrack)
- return myTracks[i];
- }
-
- return NULL;
- }*/
-
-void FileMatroska::track_SetName(Track * aTrack, const std::string & aName)
-{
- if (IsMyTrack(aTrack)) {
- aTrack->SetName(aName);
- }
-}
-
-void FileMatroska::track_SetLaced(Track * aTrack, bool bLaced)
-{
- if (IsMyTrack(aTrack)) {
- aTrack->SetLaced(bLaced);
- }
-}
-
-bool FileMatroska::AddFrame(Track * aTrack, const std::uint32_t aTimecode, const binary *aFrame, const std::uint32_t aFrameSize,
- bool aKeyFrame, bool aBFrame)
-{
- try {
- // make sure we know that track
- if (IsMyTrack(aTrack)) {
- // pass the cluster to the track
- // handle the creation of a new cluster if needed
- if (aTrack->AddFrame(aTimecode, aFrame, aFrameSize, aKeyFrame, aBFrame)) {
- while (!aTrack->SerialiseBlock(myCurrWriteCluster)) {
- /// \todo handle errors
- std::uint32_t aNbBlock;
- myStreamInfo.ClusterSize += myCurrWriteCluster.Render(myFile, aNbBlock);
- myStreamInfo.NumberBlock += aNbBlock;
- myCurrWriteCluster.Flush();
- }
- }
- return true;
- }
- return false;
- }
- catch (exception & Ex) {
- throw Ex;
- }
-}
-
-void FileMatroska::Flush()
-{
- std::uint32_t aNbBlock;
- myStreamInfo.ClusterSize += myCurrWriteCluster.Render(myFile,aNbBlock);
- myStreamInfo.NumberBlock += aNbBlock;
-}
-
-std::uint32_t FileMatroska::ReadHead()
-{
- try {
- std::uint32_t result = myMainHeader.Read(myFile, myStreamInfo);
-
- return result;
- }
- catch (exception & Ex) {
- throw Ex;
- }
-}
-
-std::uint32_t FileMatroska::ReadTracks()
-{
- try {
- std::uint32_t result = 0;
-
- // seek to the start of the Track Entries
- myFile.setFilePointer(myStreamInfo.TrackEntryPosition);
- // get the number of Track Entries
- std::uint8_t TrackNumber = myStreamInfo.TrackEntriesSize / myStreamInfo.TrackEntrySize;
- // read all the Track Entries
- myTracks.clear();
- for (std::uint8_t TrackIdx = 0; TrackIdx<TrackNumber; TrackIdx ++) {
- Track * tmpTrack = Track::ReadEntry(myFile, TrackIdx+1, myStreamInfo);
- if (tmpTrack == NULL)
- throw 0;
-
- myTracks.push_back(tmpTrack);
- }
-
- return result;
- }
- catch (exception & Ex) {
- throw Ex;
- }
-}
-
-std::uint32_t FileMatroska::ReadCodec()
-{
- try {
- // seek to the start of the Track Entries
- myFile.setFilePointer(myStreamInfo.CodecEntryPosition);
-
- std::uint32_t result = CodecHeader::Read(myFile, myTracks);
-
- return result;
- }
- catch (exception & Ex) {
- throw Ex;
- }
-}
-
-inline bool FileMatroska::IsMyTrack(const Track * aTrack) const
-{
- if (aTrack == 0)
- throw 0;
-
- return std::any_of(myTracks.begin(), myTracks.end(), aTrack);
-}
-
-void FileMatroska::SelectReadingTrack(Track * aTrack, bool select)
-{
- if (IsMyTrack(aTrack)) {
- // here we have the right track
- // check if it's not already selected
- for (const auto& num : mySelectedTracks) {
- if (num == aTrack->TrackNumber())
- break;
- }
-
- if (select && j == mySelectedTracks.end())
- mySelectedTracks.push_back(aTrack->TrackNumber());
- else if (!select && j != mySelectedTracks.end())
- mySelectedTracks.erase(j);
-
- std::sort(mySelectedTracks.begin(), mySelectedTracks.end());
- }
-}
-
-inline bool FileMatroska::IsReadingTrack(const std::uint8_t aTrackNumber) const
-{
- return std::any_of(mySelectedTracks.begin(), mySelectedTracks.end(), [=](int track){ return track >= aTrackNumber; })
-}
-
-//
-
-void FileMatroska::Track_GetInfo(const Track * aTrack, TrackInfo & aTrackInfo) const
-{
- if (IsMyTrack(aTrack)) {
- aTrack->GetInfo(aTrackInfo);
- }
-}
-
-// Audio related getters/setters
-
-void FileMatroska::Track_GetInfo_Audio(const Track * aTrack, TrackInfoAudio & aTrackInfo) const
-{
- if (IsMyTrack(aTrack)) {
- aTrack->GetInfoAudio(aTrackInfo);
- }
-}
-
-void FileMatroska::Track_SetInfo_Audio(Track * aTrack, const TrackInfoAudio & aTrackInfo)
-{
- if (IsMyTrack(aTrack)) {
- aTrack->SetInfoAudio(aTrackInfo);
- }
-}
-
-// Video related getters/setters
-
-void FileMatroska::Track_GetInfo_Video(const Track * aTrack, TrackInfoVideo & aTrackInfo) const
-{
- if (IsMyTrack(aTrack)) {
- aTrack->GetInfoVideo(aTrackInfo);
- }
-}
-
-void FileMatroska::Track_SetInfo_Video(Track * aTrack, const TrackInfoVideo & aTrackInfo)
-{
- if (IsMyTrack(aTrack)) {
- aTrack->SetInfoVideo(aTrackInfo);
- }
-}
-
-/*!
- \todo exit when there is no Block left
-*/
-bool FileMatroska::ReadFrame(Track * & aTrack, std::uint32_t & aTimecode, const binary * & aFrame, std::uint32_t & aFrameSize,
- bool & aKeyFrame, bool & aBFrame)
-{
- if (myCurrReadBlockTrack == 0) {
- do {
- if (myReadBlockNumber >= myStreamInfo.NumberBlock) {
- // myReadBlockNumber = myStreamInfo.NumberBlock;
- return false;
- }
-
- // get the next frame in the file
- if (!myCurrReadCluster.BlockLeft()) {
- myCurrReadCluster.Flush();
- try {
- myCurrReadCluster.FindHead(myFile);
- }
- catch (exception & Ex) {
- return false;
- }
- }
-
- myCurrReadCluster.GetBlock( myCurrReadBlock, myCurrReadBlockSize, myCurrReadBlockTrack );
- myReadBlockNumber++;
- } while (!IsReadingTrack(myCurrReadBlockTrack));
-
- // get the track associated (normally from myTracks)
- aTrack = myTracks[myCurrReadBlockTrack-1];
- // get the next frame from the current block
- aTrack->HandleBlock(myCurrReadBlock, myCurrReadBlockSize);
- } else {
- // get the track associated (normally from myTracks)
- aTrack = myTracks[myCurrReadBlockTrack-1];
- }
-
- Frame * myReadFrame;
- aTrack->GetNextFrame(aTimecode, myReadFrame, aKeyFrame, aBFrame);
- aFrame = myReadFrame->buf();
- aFrameSize = myReadFrame->length();
-
- if (aTrack->NoFrameLeft()) {
- aTrack->FlushBlock();
- myCurrReadBlockTrack = 0;
- }
-
- return true;
-}
-#endif // OLD
-
} // namespace libmatroska
void matroska_init()
}
}
}
-
-#ifdef OLD
- std::uint8_t TrackNumber = MuxedFile.GetTrackNumber();
-
- TrackInfo *Tracks = new TrackInfo[TrackNumber];
- TrackInfoAudio aAudioTrack;
- TrackInfoVideo aVideoTrack;
-
- Track * track1 = MuxedFile.GetTrack(1);
- Track * track2 = MuxedFile.GetTrack(2);
- Track * track3 = MuxedFile.GetTrack(3); // should be 0
- // get information about the 1st track
-
- MuxedFile.Track_GetInfo(track1, Tracks[0]);
- displayTrackInfo(Tracks[0]);
-
- if (Tracks[0].TrackType == track_audio) {
- MuxedFile.Track_GetInfo_Audio(track1, aAudioTrack);
- displayAudioInfo(aAudioTrack);
- }
- else
- cout << "the expected audio track is not an audio one :(" << endl;
-
- MuxedFile.Track_GetInfo(track3, Tracks[2]);
- displayTrackInfo(Tracks[2]);
-
- if (Tracks[2].TrackType == track_video) {
- MuxedFile.Track_GetInfo_Video(track3, aVideoTrack);
- displayVideoInfo(aVideoTrack);
- }
- else
- cout << "the expected video track is not an video one :(" << endl;
-
- // let's read only track1 (audio)
- MuxedFile.SelectReadingTrack(track1);
- MuxedFile.SelectReadingTrack(track2);
- MuxedFile.SelectReadingTrack(track1,false);
- MuxedFile.SelectReadingTrack(track1);
- MuxedFile.SelectReadingTrack(track2,false);
- MuxedFile.SelectReadingTrack(track2);
- MuxedFile.SelectReadingTrack(track3);
-
- // read the frames from the selected tracks and put them in an output file
- StdIOCallback Output_file1("out-binr.bin", MODE_CREATE);
- StdIOCallback Output_file2("out-text.bin", MODE_CREATE);
- StdIOCallback Output_file3("out-vide.bin", MODE_CREATE);
-
- Track * TrackRead;
- std::uint32_t timecode; // not used yet
- binary *aFrame;
- std::uint32_t aFrameSize;
- while (MuxedFile.ReadFrame(TrackRead, timecode, aFrame, aFrameSize))
- {
- if (TrackRead == track1)
- {
- Output_file1.write(aFrame, aFrameSize);
- }
- else if (TrackRead == track2)
- {
- Output_file2.write(aFrame, aFrameSize);
- }
- else if (TrackRead == track3)
- {
- Output_file3.write(aFrame, aFrameSize);
- }
- else cout << "received a frame from an unwanted track" << endl;
- }
- delete[] Tracks;
-#endif // OLD
}
catch (exception & Ex)
{