diff options
| author | Carl Hetherington <cth@carlh.net> | 2024-03-22 19:20:29 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2024-04-21 23:06:35 +0200 |
| commit | d4abae4fdecc33cac471b63c0383be27cb2409fa (patch) | |
| tree | c91945133589016b24e29c7214aa9ce10aceef33 /src | |
| parent | 48feccc34ebb795b2547823e34c2cd042ec2c7e8 (diff) | |
Add the DCP-o-matic-specific API additions for MPEG2 (as added previously for JPEG2000).mpeg2
Diffstat (limited to 'src')
| -rwxr-xr-x | src/AS_DCP.h | 10 | ||||
| -rwxr-xr-x | src/AS_DCP_MPEG2.cpp | 104 | ||||
| -rwxr-xr-x | src/MPEG2_Parser.cpp | 46 |
3 files changed, 140 insertions, 20 deletions
diff --git a/src/AS_DCP.h b/src/AS_DCP.h index e41d70c..63e6665 100755 --- a/src/AS_DCP.h +++ b/src/AS_DCP.h @@ -737,6 +737,7 @@ namespace ASDCP { // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. Result_t OpenRead(const std::string& filename) const; + Result_t OpenRead(uint8_t const* data, int size) const; // Fill a VideoDescriptor struct with the values from the file's header. // Returns RESULT_INIT if the file is not open. @@ -775,16 +776,21 @@ namespace ASDCP { // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. Result_t OpenWrite(const std::string& filename, const WriterInfo&, - const VideoDescriptor&, ui32_t HeaderSize = 16384); + const VideoDescriptor&, ui32_t HeaderSize = 16384, bool overwrite = false); // Writes a frame of essence to the MXF file. If the optional AESEncContext // argument is present, the essence is encrypted prior to writing. // Fails if the file is not open, is finalized, or an operating system // error occurs. - Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); + Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0); + + Result_t FakeWriteFrame(int size, FrameType_t frame_type, bool gop_start, bool closed_gop, ui8_t temporal_offset); // Closes the MXF file, writing the index and revised header. Result_t Finalize(); + + // Return the current file offset in the MXF file that we are writing. + ui64_t Tell() const; }; // A class which reads MPEG frame data from an AS-DCP format MXF file. diff --git a/src/AS_DCP_MPEG2.cpp b/src/AS_DCP_MPEG2.cpp index 807e58b..10a25d1 100755 --- a/src/AS_DCP_MPEG2.cpp +++ b/src/AS_DCP_MPEG2.cpp @@ -542,9 +542,10 @@ public: virtual ~h__Writer(){} - Result_t OpenWrite(const std::string&, ui32_t HeaderSize); + Result_t OpenWrite(const std::string&, ui32_t HeaderSize, bool overwrite = false); Result_t SetSourceStream(const VideoDescriptor&); - Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); + Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0); + Result_t FakeWriteFrame(int size, FrameType_t frame_type, bool gop_start, bool closed_gop, ui8_t temporal_offset); Result_t Finalize(); }; @@ -552,12 +553,21 @@ public: // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::MPEG2::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize) +ASDCP::MPEG2::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize, bool overwrite) { if ( ! m_State.Test_BEGIN() ) return RESULT_STATE; - Result_t result = m_File.OpenWrite(filename); + Result_t result = RESULT_OK; + if (overwrite) + { + result = m_File.OpenModify(filename); + m_File.Seek(0); + } + else + { + result = m_File.OpenWrite(filename); + } if ( ASDCP_SUCCESS(result) ) { @@ -606,7 +616,7 @@ ASDCP::MPEG2::MXFWriter::h__Writer::SetSourceStream(const VideoDescriptor& VDesc // ASDCP::Result_t ASDCP::MPEG2::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, - HMACContext* HMAC) + HMACContext* HMAC, std::string* hash) { Result_t result = RESULT_OK; @@ -617,7 +627,7 @@ ASDCP::MPEG2::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& FrameBuf, AESE Entry.StreamOffset = m_StreamOffset; if ( ASDCP_SUCCESS(result) ) - result = WriteEKLVPacket(FrameBuf, m_EssenceUL, MXF_BER_LENGTH, Ctx, HMAC); + result = WriteEKLVPacket(FrameBuf, m_EssenceUL, MXF_BER_LENGTH, Ctx, HMAC, hash); if ( ASDCP_FAILURE(result) ) return result; @@ -661,6 +671,62 @@ ASDCP::MPEG2::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& FrameBuf, AESE } +ASDCP::Result_t +ASDCP::MPEG2::MXFWriter::h__Writer::FakeWriteFrame(int size, FrameType_t frame_type, bool gop_start, bool closed_gop, ui8_t temporal_offset) +{ + Result_t result = RESULT_OK; + + if ( m_State.Test_READY() ) + result = m_State.Goto_RUNNING(); // first time through, get the body location + + IndexTableSegment::IndexEntry Entry; + Entry.StreamOffset = m_StreamOffset; + + if ( ASDCP_SUCCESS(result) ) + result = FakeWriteEKLVPacket(size); + + if ( ASDCP_FAILURE(result) ) + return result; + + // create mxflib flags + int Flags = 0; + + switch (frame_type) + { + case FRAME_I: Flags = 0x00; break; + case FRAME_P: Flags = 0x22; break; + case FRAME_B: Flags = 0x33; break; + case FRAME_U: break; + } + + if (gop_start) + { + m_GOPOffset = 0; + Flags |= 0x40; + + if (closed_gop) + Flags |= 0x80; + } + + // update the index manager + Entry.TemporalOffset = - temporal_offset; + Entry.KeyFrameOffset = 0 - m_GOPOffset; + Entry.Flags = Flags; + /* + fprintf(stderr, "to: %4hd ko: %4hd c1: %4hd c2: %4hd fl: 0x%02x\n", + Entry.TemporalOffset, Entry.KeyFrameOffset, + m_GOPOffset + Entry.TemporalOffset, + Entry.KeyFrameOffset - Entry.TemporalOffset, + Entry.Flags); + */ + m_FooterPart.PushIndexEntry(Entry); + m_FramesWritten++; + m_GOPOffset++; + + return RESULT_OK; +} + + // Closes the MXF file, writing the index and other closing information. // ASDCP::Result_t @@ -736,7 +802,7 @@ ASDCP::MPEG2::MXFWriter::RIP() // the operation cannot be completed. ASDCP::Result_t ASDCP::MPEG2::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, - const VideoDescriptor& VDesc, ui32_t HeaderSize) + const VideoDescriptor& VDesc, ui32_t HeaderSize, bool overwrite) { if ( Info.LabelSetType == LS_MXF_SMPTE ) m_Writer = new h__Writer(&DefaultSMPTEDict()); @@ -744,8 +810,8 @@ ASDCP::MPEG2::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo m_Writer = new h__Writer(&DefaultInteropDict()); m_Writer->m_Info = Info; - - Result_t result = m_Writer->OpenWrite(filename, HeaderSize); + + Result_t result = m_Writer->OpenWrite(filename, HeaderSize, overwrite); if ( ASDCP_SUCCESS(result) ) result = m_Writer->SetSourceStream(VDesc); @@ -762,12 +828,21 @@ ASDCP::MPEG2::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo // Fails if the file is not open, is finalized, or an operating system // error occurs. ASDCP::Result_t -ASDCP::MPEG2::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC) +ASDCP::MPEG2::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC, std::string* hash) { if ( m_Writer.empty() ) return RESULT_INIT; - return m_Writer->WriteFrame(FrameBuf, Ctx, HMAC); + return m_Writer->WriteFrame(FrameBuf, Ctx, HMAC, hash); +} + +ASDCP::Result_t +ASDCP::MPEG2::MXFWriter::FakeWriteFrame(int size, FrameType_t frame_type, bool gop_start, bool closed_gop, ui8_t temporal_offset) +{ + if ( m_Writer.empty() ) + return RESULT_INIT; + + return m_Writer->FakeWriteFrame(size, frame_type, gop_start, closed_gop, temporal_offset); } // Closes the MXF file, writing the index and other closing information. @@ -781,6 +856,13 @@ ASDCP::MPEG2::MXFWriter::Finalize() } +ui64_t +ASDCP::MPEG2::MXFWriter::Tell() const +{ + return m_Writer->m_File.TellPosition(); +} + + // // end AS_DCP_MPEG2.cpp // diff --git a/src/MPEG2_Parser.cpp b/src/MPEG2_Parser.cpp index 3eefc96..05bb17c 100755 --- a/src/MPEG2_Parser.cpp +++ b/src/MPEG2_Parser.cpp @@ -382,11 +382,14 @@ class Parser::h__Parser ASDCP_NO_COPY_CONSTRUCT(h__Parser); + Result_t Parse(ui32_t read_count); + public: h__Parser() : m_TmpBuffer(VESReadSize*8) {} ~h__Parser() { Close(); } Result_t OpenRead(const std::string& filename); + Result_t OpenRead(uint8_t const* data, int size); void Close(); Result_t Reset(); Result_t ReadFrame(FrameBuffer&); @@ -427,6 +430,25 @@ ASDCP::MPEG2::Parser::h__Parser::OpenRead(const std::string& filename) if ( ASDCP_SUCCESS(result) ) { + result = Parse(read_count); + } + + return result; +} + + +ASDCP::Result_t +ASDCP::MPEG2::Parser::h__Parser::OpenRead(uint8_t const* data, int size) +{ + ui32_t const read_count = std::min(m_TmpBuffer.Capacity(), static_cast<ui32_t>(size)); + memcpy(m_TmpBuffer.Data(), data, read_count); + return Parse(read_count); +} + + +ASDCP::Result_t +ASDCP::MPEG2::Parser::h__Parser::Parse(ui32_t read_count) +{ const byte_t* p = m_TmpBuffer.RoData(); // the mxflib parser demanded the file start with a sequence header. @@ -442,12 +464,8 @@ ASDCP::MPEG2::Parser::h__Parser::OpenRead(const std::string& filename) return RESULT_RAW_FORMAT; } - if ( ASDCP_SUCCESS(result) ) - { - m_Parser.SetDelegate(&m_ParamsDelegate); - result = m_Parser.Parse(p, read_count); - } - } + m_Parser.SetDelegate(&m_ParamsDelegate); + auto result = m_Parser.Parse(p, read_count); if ( ASDCP_SUCCESS(result) ) { @@ -459,7 +477,7 @@ ASDCP::MPEG2::Parser::h__Parser::OpenRead(const std::string& filename) if ( ASDCP_FAILURE(result) ) { - DefaultLogSink().Error("Unable to identify a wrapping mode for the essence in file \"%s\"\n", filename.c_str()); + DefaultLogSink().Error("Unable to identify a wrapping mode for the essence\n"); m_FileReader.Close(); } @@ -594,6 +612,20 @@ ASDCP::MPEG2::Parser::OpenRead(const std::string& filename) const return result; } +ASDCP::Result_t +ASDCP::MPEG2::Parser::OpenRead(uint8_t const* data, int size) const +{ + const_cast<ASDCP::MPEG2::Parser*>(this)->m_Parser = new h__Parser; + + Result_t result = m_Parser->OpenRead(data, size); + + if ( ASDCP_FAILURE(result) ) + const_cast<ASDCP::MPEG2::Parser*>(this)->m_Parser.release(); + + return result; +} + + // Rewinds the stream to the beginning. ASDCP::Result_t ASDCP::MPEG2::Parser::Reset() const |
