#AC_CONFIG_HEADER([src/config.h])
AM_INIT_AUTOMAKE([1.9 foreign])
+AC_CONFIG_MACRO_DIR([m4])
+
# Checks for programs.
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_ARG_ENABLE([freedist],
[ --enable-freedist ensure source distribution is of BSD-licensed code],
[case "${enableval}" in
- yes) freedist=true ;;
+ yes) freedist=true
+ AC_MSG_WARN([BSD licensed ASDCPlib creation ENABLED.]) ;;
no) freedist=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-freedist]) ;;
esac],[freedist=false])
esac],[random_case_UUID=false])
AM_CONDITIONAL([ENABLE_RANDOM_UUID], [test x$random_case_UUID = xtrue])
AC_ARG_ENABLE([as-02],
- [ --enable-as-02 enable supprt for SMPTE ST 2067-5 MXF files, A.K.A. AS-02],
+ [ --enable-as-02 enable support for SMPTE ST 2067-5 MXF files, A.K.A. AS-02],
[case "${enableval}" in
yes) as_02_use=true ;;
no) as_02_use=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-as-02]) ;;
esac],[as_02_use=false])
- AM_CONDITIONAL([AS_02_USE], [test x$as_02_use = xtrue])
+ AM_CONDITIONAL([USE_AS_02], [test x$as_02_use = xtrue])
# Checks for libraries.
AC_CHECK_LIB([pthread], [pthread_create])
using Kumu::Result_t;
namespace MXF {
-#if 1
+#if 0
//
class OP1aIndexBodyPartion : public ASDCP::MXF::Partition
{
//------------------------------------------------------------------------------------------
-static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE ST 422 frame wrapping of JPEG 2000 codestreams";
+static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE ST 422 / ST 2067-5 frame wrapping of JPEG 2000 codestreams";
static std::string PICT_DEF_LABEL = "Image Track";
//------------------------------------------------------------------------------------------
Result_t OpenRead(const char*, EssenceType_t);
Result_t ReadFrame(ui32_t, ASDCP::JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
- Result_t MD_to_JP2K_PDesc(ASDCP::JP2K::PictureDescriptor& PDesc);
-
- Result_t OpenMXFRead(const char* filename);
- // positions file before reading
- Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
- const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
-
- // reads from current position
- Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
- const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
-
};
//
-ASDCP::Result_t
-AS_02::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(ASDCP::JP2K::PictureDescriptor& PDesc)
-{
- memset(&PDesc, 0, sizeof(PDesc));
- ASDCP::MXF::RGBAEssenceDescriptor* PDescObj = (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
-
- PDesc.EditRate = m_EditRate;
- PDesc.SampleRate = m_SampleRate;
- assert(PDescObj->ContainerDuration <= 0xFFFFFFFFL);
- PDesc.ContainerDuration = (ui32_t) PDescObj->ContainerDuration;
- PDesc.StoredWidth = PDescObj->StoredWidth;
- PDesc.StoredHeight = PDescObj->StoredHeight;
- PDesc.AspectRatio = PDescObj->AspectRatio;
-
- if ( m_EssenceSubDescriptor != 0 )
- {
- PDesc.Rsize = m_EssenceSubDescriptor->Rsize;
- PDesc.Xsize = m_EssenceSubDescriptor->Xsize;
- PDesc.Ysize = m_EssenceSubDescriptor->Ysize;
- PDesc.XOsize = m_EssenceSubDescriptor->XOsize;
- PDesc.YOsize = m_EssenceSubDescriptor->YOsize;
- PDesc.XTsize = m_EssenceSubDescriptor->XTsize;
- PDesc.YTsize = m_EssenceSubDescriptor->YTsize;
- PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
- PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
- PDesc.Csize = m_EssenceSubDescriptor->Csize;
-
- // PictureComponentSizing
- ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
-
- if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
- memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
-
- else
- DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
-
- // CodingStyleDefault
- memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
- memcpy(&PDesc.CodingStyleDefault,
- m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
- m_EssenceSubDescriptor->CodingStyleDefault.Length());
-
- // QuantizationDefault
- memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
- memcpy(&PDesc.QuantizationDefault,
- m_EssenceSubDescriptor->QuantizationDefault.RoData(),
- m_EssenceSubDescriptor->QuantizationDefault.Length());
-
- PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
- }
-
- return RESULT_OK;
-}
-
-//
-//
-ASDCP::Result_t
+Result_t
AS_02::JP2K::MXFReader::h__Reader::OpenRead(const char* filename, ASDCP::EssenceType_t type)
{
Result_t result = OpenMXFRead(filename);
return RESULT_STATE;
}
- result = MD_to_JP2K_PDesc(m_PDesc);
+ assert(m_EssenceDescriptor);
+ assert(m_EssenceSubDescriptor);
+ result = MD_to_JP2K_PDesc(*m_EssenceDescriptor, *m_EssenceSubDescriptor, m_EditRate, m_SampleRate, m_PDesc);
}
return result;
//
//
-ASDCP::Result_t
+Result_t
AS_02::JP2K::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::JP2K::FrameBuffer& FrameBuf,
ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC)
{
// Fill the struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
-ASDCP::Result_t AS_02::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
+Result_t
+AS_02::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
{
if ( m_Reader && m_Reader->m_File.IsOpen() )
{
// Fill the struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
-ASDCP::Result_t AS_02::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
+Result_t
+AS_02::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
{
if ( m_Reader && m_Reader->m_File.IsOpen() )
{
PictureDescriptor m_PDesc;
byte_t m_EssenceUL[SMPTE_UL_LENGTH];
- //new attributes for AS-02 support
- AS_02::IndexStrategy_t m_IndexStrategy; //Shim parameter index_strategy_frame/clip
- ui32_t m_PartitionSpace; //Shim parameter partition_spacing
-
- h__Writer(const Dictionary& d) : h__AS02Writer(d), m_EssenceSubDescriptor(0), m_IndexStrategy(AS_02::IS_FOLLOW), m_PartitionSpace(60) {
+ h__Writer(const Dictionary& d) : h__AS02Writer(d), m_EssenceSubDescriptor(0) {
memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
}
const ui32_t& PartitionSpace, const ui32_t& HeaderSize);
Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
- Result_t WriteFrame(const ASDCP::JP2K::FrameBuffer&, bool add_index, ASDCP::AESEncContext*, ASDCP::HMACContext*);
+ Result_t WriteFrame(const ASDCP::JP2K::FrameBuffer&, ASDCP::AESEncContext*, ASDCP::HMACContext*);
Result_t Finalize();
- Result_t JP2K_PDesc_to_MD(ASDCP::JP2K::PictureDescriptor& PDesc);
-
- //void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
- // const std::string& TrackName, const UL& EssenceUL,
- // const UL& DataDefinition, const std::string& PackageLabel);
- //void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate,
- // const std::string& TrackName, const UL& DataDefinition,
- // const std::string& PackageLabel);
- //void AddEssenceDescriptor(const UL& WrappingUL);
- //Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
-
- ////new method to create BodyPartition for essence and index
- //Result_t CreateBodyPartPair();
- ////new method to finalize BodyPartion(index)
- //Result_t CompleteIndexBodyPart();
-
- // reimplement these functions in AS_02_PCM to support modifications for AS-02
- //Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
- // const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
- Result_t WriteMXFFooter();
-
-
};
-const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
-const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
-static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
-
-//
-ASDCP::Result_t
-AS_02::JP2K::MXFWriter::h__Writer::JP2K_PDesc_to_MD(ASDCP::JP2K::PictureDescriptor& PDesc)
-{
- assert(m_EssenceDescriptor);
- assert(m_EssenceSubDescriptor);
- ASDCP::MXF::RGBAEssenceDescriptor* PDescObj = (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
-
- PDescObj->ContainerDuration = PDesc.ContainerDuration;
- PDescObj->SampleRate = PDesc.EditRate;
- PDescObj->FrameLayout = 0;
- PDescObj->StoredWidth = PDesc.StoredWidth;
- PDescObj->StoredHeight = PDesc.StoredHeight;
- PDescObj->AspectRatio = PDesc.AspectRatio;
-
- // if ( m_Info.LabelSetType == LS_MXF_SMPTE )
- // {
- // PictureEssenceCoding UL =
- // Video Line Map ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
- // CaptureGamma UL =
- // ComponentMaxRef ui32_t = 4095
- // ComponentMinRef ui32_t = 0
- // PixelLayout byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
- // }
-
- assert(m_Dict);
- if ( PDesc.StoredWidth < 2049 )
- {
- PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
- m_EssenceSubDescriptor->Rsize = 3;
- }
- else
- {
- PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
- m_EssenceSubDescriptor->Rsize = 4;
- }
-
- m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
- m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
- m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
- m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
- m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
- m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
- m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
- m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
- m_EssenceSubDescriptor->Csize = PDesc.Csize;
-
- const ui32_t tmp_buffer_len = 1024;
- byte_t tmp_buffer[tmp_buffer_len];
-
- // slh: this has to be done dynamically since the number of components is not always 3
- *(ui32_t*)tmp_buffer = KM_i32_BE(m_EssenceSubDescriptor->Csize);
- *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
- memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * m_EssenceSubDescriptor->Csize);
- const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * m_EssenceSubDescriptor->Csize);
-
- /*
- *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
- *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
- memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
- const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
- */
-
- memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
- m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
-
- ui32_t precinct_set_size = 0, i;
- for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
- precinct_set_size++;
-
- ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
- memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
- m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
-
- ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
- memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
- m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
-
- return RESULT_OK;
-}
-
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
-ASDCP::Result_t
+Result_t
AS_02::JP2K::MXFWriter::h__Writer::OpenWrite(const char* filename, EssenceType_t type, const AS_02::IndexStrategy_t& IndexStrategy,
- const ui32_t& PartitionSpace, const ui32_t& HeaderSize)
+ const ui32_t& PartitionSpace_sec, const ui32_t& HeaderSize)
{
if ( ! m_State.Test_BEGIN() )
return RESULT_STATE;
- ASDCP::Result_t result = m_File.OpenWrite(filename);
+ if ( m_IndexStrategy != AS_02::IS_FOLLOW )
+ {
+ DefaultLogSink().Error("Only strategy IS_FOLLOW is supported at this time.\n");
+ return Kumu::RESULT_NOTIMPL;
+ }
+
+ Result_t result = m_File.OpenWrite(filename);
if ( ASDCP_SUCCESS(result) )
{
m_IndexStrategy = IndexStrategy;
- m_PartitionSpace = PartitionSpace;
+ m_PartitionSpace = PartitionSpace_sec; // later converted to edit units by SetSourceStream()
m_HeaderSize = HeaderSize;
- RGBAEssenceDescriptor* tmp_rgba = new RGBAEssenceDescriptor(m_Dict);
- tmp_rgba->ComponentMaxRef = 4095;
- tmp_rgba->ComponentMinRef = 0;
- m_EssenceDescriptor = tmp_rgba;
+ m_EssenceDescriptor = new RGBAEssenceDescriptor(m_Dict);
m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor(m_Dict);
m_EssenceSubDescriptorList.push_back((InterchangeObject*)m_EssenceSubDescriptor);
}
// Automatically sets the MXF file's metadata from the first jpeg codestream stream.
-ASDCP::Result_t
+Result_t
AS_02::JP2K::MXFWriter::h__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
{
assert(m_Dict);
LocalEditRate = PDesc.EditRate;
m_PDesc = PDesc;
- Result_t result = JP2K_PDesc_to_MD(m_PDesc);
+ assert(m_Dict);
+ Result_t result = JP2K_PDesc_to_MD(m_PDesc, *m_Dict,
+ static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor),
+ m_EssenceSubDescriptor);
+
+ static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor)->ComponentMaxRef = 4095; /// TODO: set with magic or some such thing
+ static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor)->ComponentMinRef = 0;
if ( ASDCP_SUCCESS(result) )
{
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
//
-ASDCP::Result_t
-AS_02::JP2K::MXFWriter::h__Writer::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf, bool add_index,
+Result_t
+AS_02::JP2K::MXFWriter::h__Writer::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf,
AESEncContext* Ctx, HMACContext* HMAC)
+#if 1
+{
+ Result_t result = RESULT_OK;
+
+ if ( m_State.Test_READY() )
+ result = m_State.Goto_RUNNING(); // first time through
+
+ ui64_t StreamOffset = m_StreamOffset;
+
+ if ( ASDCP_SUCCESS(result) )
+ result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ IndexTableSegment::IndexEntry Entry;
+ Entry.StreamOffset = StreamOffset;
+ m_IndexWriter.PushIndexEntry(Entry);
+ }
+
+ m_FramesWritten++;
+ return result;
+}
+#else
{
Result_t result = RESULT_OK;
m_FramesWritten++;
return result;
}
-
+#endif
// Closes the MXF file, writing the index and other closing information.
//
-ASDCP::Result_t
+Result_t
AS_02::JP2K::MXFWriter::h__Writer::Finalize()
{
- Result_t result = RESULT_OK;
-
if ( ! m_State.Test_RUNNING() )
return RESULT_STATE;
- m_State.Goto_FINAL();
+ Result_t result = m_State.Goto_FINAL();
- //the last Frame was written, complete the BodyPartion(Index), after that write the MXF-Footer
- result = CompleteIndexBodyPart();
+ if ( ASDCP_SUCCESS(result) )
+ result = WriteAS02Footer();
- if ( ASDCP_FAILURE(result) ){
- return result;
- }
- return WriteMXFFooter();
+ return result;
}
+
//------------------------------------------------------------------------------------------
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
-ASDCP::Result_t
+Result_t
AS_02::JP2K::MXFWriter::OpenWrite(const char* filename, const ASDCP::WriterInfo& Info,
const ASDCP::JP2K::PictureDescriptor& PDesc,
const IndexStrategy_t& Strategy,
m_Writer = new AS_02::JP2K::MXFWriter::h__Writer(DefaultSMPTEDict());
m_Writer->m_Info = Info;
- ASDCP::Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, Strategy, PartitionSpace, HeaderSize);
+ Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, Strategy, PartitionSpace, HeaderSize);
if ( ASDCP_SUCCESS(result) )
result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
return result;
}
-
// 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.
-ASDCP::Result_t
+Result_t
AS_02::JP2K::MXFWriter::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
{
if ( m_Writer.empty() )
return RESULT_INIT;
- return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
+ return m_Writer->WriteFrame(FrameBuf, Ctx, HMAC);
}
// Closes the MXF file, writing the index and other closing information.
-ASDCP::Result_t
+Result_t
AS_02::JP2K::MXFWriter::Finalize()
{
if ( m_Writer.empty() )
}
}
+ //
+ class AS02IndexWriter : public ASDCP::MXF::Partition
+ {
+ ASDCP::MXF::IndexTableSegment* m_CurrentSegment;
+ ui32_t m_BytesPerEditUnit;
+ ASDCP::MXF::Rational m_EditRate;
+
+ KM_NO_COPY_CONSTRUCT(AS02IndexWriter);
+ AS02IndexWriter();
+
+ public:
+ const ASDCP::Dictionary*& m_Dict;
+ Kumu::fpos_t m_ECOffset;
+ ASDCP::IPrimerLookup* m_Lookup;
+
+ AS02IndexWriter(const ASDCP::Dictionary*&);
+ virtual ~AS02IndexWriter();
+
+ Result_t WriteToFile(Kumu::FileWriter& Writer);
+ void ResetCBR(Kumu::fpos_t offset);
+ void Dump(FILE* = 0);
+
+ ui32_t GetDuration() const;
+ void PushIndexEntry(const ASDCP::MXF::IndexTableSegment::IndexEntry&);
+ void SetIndexParamsCBR(ASDCP::IPrimerLookup* lookup, ui32_t size, const ASDCP::Rational& Rate);
+ void SetIndexParamsVBR(ASDCP::IPrimerLookup* lookup, const ASDCP::Rational& Rate, Kumu::fpos_t offset);
+ };
+
//
class h__AS02Reader : public ASDCP::MXF::TrackFileReader<ASDCP::MXF::OP1aHeader, AS_02::MXF::AS02IndexReader>
{
h__AS02Reader();
public:
- Partition *m_pCurrentBodyPartition;
- AS_02::MXF::OP1aIndexBodyPartion* m_pCurrentIndexPartition;
- ui64_t m_EssenceStart;
- std::vector<Partition*> m_BodyPartList;
- ui32_t m_start_pos;
- ui32_t m_PartitionSpace;
- IndexStrategy_t m_IndexStrategy; //Shim parameter index_strategy_frame/clip
+ // Partition *m_pCurrentBodyPartition;
+ // ui64_t m_EssenceStart;
+ // std::vector<Partition*> m_BodyPartList;
+ // ui32_t m_start_pos;
+ // ui32_t m_PartitionSpace;
+ // IndexStrategy_t m_IndexStrategy; //Shim parameter index_strategy_frame/clip
h__AS02Reader(const ASDCP::Dictionary&);
virtual ~h__AS02Reader();
Result_t OpenMXFRead(const char* filename);
+
Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
const byte_t* EssenceUL, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC);
- Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
- i8_t& temporalOffset, i8_t& keyFrameOffset);
+ Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset);
};
//
h__AS02Writer();
public:
- AS_02::MXF::OP1aIndexBodyPartion* m_CurrentIndexBodyPartition;
- ui64_t m_BodyOffset;
- ui32_t m_PartitionSpace;
+ AS02IndexWriter m_IndexWriter;
+ ui32_t m_PartitionSpace; // edit units per partition
IndexStrategy_t m_IndexStrategy; //Shim parameter index_strategy_frame/clip
- std::vector<Partition*> m_BodyPartList;
h__AS02Writer(const Dictionary&);
virtual ~h__AS02Writer();
const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
- Result_t CreateBodyPart(const ASDCP::MXF::Rational& EditRate, ui32_t BytesPerEditUnit);
- Result_t CreateBodyPartPair();
- Result_t CompleteIndexBodyPart();
+ Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
+ AESEncContext* Ctx, HMACContext* HMAC);
Result_t WriteAS02Footer();
};
}
+const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
+const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
+static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
+
+//
+ASDCP::Result_t
+ASDCP::JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
+ const ASDCP::Dictionary& dict,
+ ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor,
+ ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor)
+{
+ if ( EssenceDescriptor == 0 || EssenceSubDescriptor == 0 )
+ return RESULT_PTR;
+
+ EssenceDescriptor->ContainerDuration = PDesc.ContainerDuration;
+ EssenceDescriptor->SampleRate = PDesc.EditRate;
+ EssenceDescriptor->FrameLayout = 0;
+ EssenceDescriptor->StoredWidth = PDesc.StoredWidth;
+ EssenceDescriptor->StoredHeight = PDesc.StoredHeight;
+ EssenceDescriptor->AspectRatio = PDesc.AspectRatio;
+
+ // if ( m_Info.LabelSetType == LS_MXF_SMPTE )
+ // {
+ // PictureEssenceCoding UL =
+ // Video Line Map ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
+ // CaptureGamma UL =
+ // ComponentMaxRef ui32_t = 4095
+ // ComponentMinRef ui32_t = 0
+ // PixelLayout byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
+ // }
+
+ if ( PDesc.StoredWidth < 2049 )
+ {
+ EssenceDescriptor->PictureEssenceCoding.Set(dict.ul(MDD_JP2KEssenceCompression_2K));
+ EssenceSubDescriptor->Rsize = 3;
+ }
+ else
+ {
+ EssenceDescriptor->PictureEssenceCoding.Set(dict.ul(MDD_JP2KEssenceCompression_4K));
+ EssenceSubDescriptor->Rsize = 4;
+ }
+
+ EssenceSubDescriptor->Xsize = PDesc.Xsize;
+ EssenceSubDescriptor->Ysize = PDesc.Ysize;
+ EssenceSubDescriptor->XOsize = PDesc.XOsize;
+ EssenceSubDescriptor->YOsize = PDesc.YOsize;
+ EssenceSubDescriptor->XTsize = PDesc.XTsize;
+ EssenceSubDescriptor->YTsize = PDesc.YTsize;
+ EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
+ EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
+ EssenceSubDescriptor->Csize = PDesc.Csize;
+
+ const ui32_t tmp_buffer_len = 1024;
+ byte_t tmp_buffer[tmp_buffer_len];
+
+ *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
+ *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
+ memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
+
+ const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
+ memcpy(EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
+ EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
+
+ ui32_t precinct_set_size = 0, i;
+ for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
+ precinct_set_size++;
+
+ ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
+ memcpy(EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
+ EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
+
+ ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
+ memcpy(EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
+ EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
+
+ return RESULT_OK;
+}
+
+
//------------------------------------------------------------------------------------------
//
// hidden, internal implementation of JPEG 2000 reader
Result_t OpenRead(const char*, EssenceType_t);
Result_t ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
- Result_t MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc);
};
//
ASDCP::Result_t
-lh__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc)
+ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::RGBAEssenceDescriptor& EssenceDescriptor,
+ const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
+ const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
+ ASDCP::JP2K::PictureDescriptor& PDesc)
{
memset(&PDesc, 0, sizeof(PDesc));
- MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
- PDesc.EditRate = m_EditRate;
- PDesc.SampleRate = m_SampleRate;
- assert(PDescObj->ContainerDuration <= 0xFFFFFFFFL);
- PDesc.ContainerDuration = (ui32_t) PDescObj->ContainerDuration;
- PDesc.StoredWidth = PDescObj->StoredWidth;
- PDesc.StoredHeight = PDescObj->StoredHeight;
- PDesc.AspectRatio = PDescObj->AspectRatio;
-
- if ( m_EssenceSubDescriptor != 0 )
+ PDesc.EditRate = EditRate;
+ PDesc.SampleRate = SampleRate;
+ assert(EssenceDescriptor.ContainerDuration <= 0xFFFFFFFFL);
+ PDesc.ContainerDuration = (ui32_t) EssenceDescriptor.ContainerDuration;
+ PDesc.StoredWidth = EssenceDescriptor.StoredWidth;
+ PDesc.StoredHeight = EssenceDescriptor.StoredHeight;
+ PDesc.AspectRatio = EssenceDescriptor.AspectRatio;
+
+ PDesc.Rsize = EssenceSubDescriptor.Rsize;
+ PDesc.Xsize = EssenceSubDescriptor.Xsize;
+ PDesc.Ysize = EssenceSubDescriptor.Ysize;
+ PDesc.XOsize = EssenceSubDescriptor.XOsize;
+ PDesc.YOsize = EssenceSubDescriptor.YOsize;
+ PDesc.XTsize = EssenceSubDescriptor.XTsize;
+ PDesc.YTsize = EssenceSubDescriptor.YTsize;
+ PDesc.XTOsize = EssenceSubDescriptor.XTOsize;
+ PDesc.YTOsize = EssenceSubDescriptor.YTOsize;
+ PDesc.Csize = EssenceSubDescriptor.Csize;
+
+ // PictureComponentSizing
+ ui32_t tmp_size = EssenceSubDescriptor.PictureComponentSizing.Length();
+
+ if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
{
- PDesc.Rsize = m_EssenceSubDescriptor->Rsize;
- PDesc.Xsize = m_EssenceSubDescriptor->Xsize;
- PDesc.Ysize = m_EssenceSubDescriptor->Ysize;
- PDesc.XOsize = m_EssenceSubDescriptor->XOsize;
- PDesc.YOsize = m_EssenceSubDescriptor->YOsize;
- PDesc.XTsize = m_EssenceSubDescriptor->XTsize;
- PDesc.YTsize = m_EssenceSubDescriptor->YTsize;
- PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
- PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
- PDesc.Csize = m_EssenceSubDescriptor->Csize;
-
- // PictureComponentSizing
- ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
-
- if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
- memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
-
- else
- DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
-
- // CodingStyleDefault
- memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
- memcpy(&PDesc.CodingStyleDefault,
- m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
- m_EssenceSubDescriptor->CodingStyleDefault.Length());
-
- // QuantizationDefault
- memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
- memcpy(&PDesc.QuantizationDefault,
- m_EssenceSubDescriptor->QuantizationDefault.RoData(),
- m_EssenceSubDescriptor->QuantizationDefault.Length());
-
- PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
+ memcpy(&PDesc.ImageComponents, EssenceSubDescriptor.PictureComponentSizing.RoData() + 8, tmp_size - 8);
+ }
+ else
+ {
+ DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
}
+ // CodingStyleDefault
+ memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
+ memcpy(&PDesc.CodingStyleDefault,
+ EssenceSubDescriptor.CodingStyleDefault.RoData(),
+ EssenceSubDescriptor.CodingStyleDefault.Length());
+
+ // QuantizationDefault
+ memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
+ memcpy(&PDesc.QuantizationDefault,
+ EssenceSubDescriptor.QuantizationDefault.RoData(),
+ EssenceSubDescriptor.QuantizationDefault.Length());
+
+ PDesc.QuantizationDefault.SPqcdLength = EssenceSubDescriptor.QuantizationDefault.Length() - 1;
return RESULT_OK;
}
return RESULT_STATE;
}
- result = MD_to_JP2K_PDesc(m_PDesc);
+ assert(m_EssenceDescriptor);
+ assert(m_EssenceSubDescriptor);
+ result = MD_to_JP2K_PDesc(*m_EssenceDescriptor, *m_EssenceSubDescriptor, m_EditRate, m_SampleRate, m_PDesc);
}
return result;
ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
Result_t Finalize();
- Result_t JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc);
};
-const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
-const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
-static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
-
-//
-ASDCP::Result_t
-lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
-{
- assert(m_EssenceDescriptor);
- assert(m_EssenceSubDescriptor);
- MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
-
- PDescObj->ContainerDuration = PDesc.ContainerDuration;
- PDescObj->SampleRate = PDesc.EditRate;
- PDescObj->FrameLayout = 0;
- PDescObj->StoredWidth = PDesc.StoredWidth;
- PDescObj->StoredHeight = PDesc.StoredHeight;
- PDescObj->AspectRatio = PDesc.AspectRatio;
-
- // if ( m_Info.LabelSetType == LS_MXF_SMPTE )
- // {
- // PictureEssenceCoding UL =
- // Video Line Map ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
- // CaptureGamma UL =
- // ComponentMaxRef ui32_t = 4095
- // ComponentMinRef ui32_t = 0
- // PixelLayout byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
- // }
-
- assert(m_Dict);
- if ( PDesc.StoredWidth < 2049 )
- {
- PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
- m_EssenceSubDescriptor->Rsize = 3;
- }
- else
- {
- PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
- m_EssenceSubDescriptor->Rsize = 4;
- }
-
- m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
- m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
- m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
- m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
- m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
- m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
- m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
- m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
- m_EssenceSubDescriptor->Csize = PDesc.Csize;
-
- const ui32_t tmp_buffer_len = 1024;
- byte_t tmp_buffer[tmp_buffer_len];
-
- *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
- *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
- memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
-
- const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
- memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
- m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
-
- ui32_t precinct_set_size = 0, i;
- for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
- precinct_set_size++;
-
- ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
- memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
- m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
-
- ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
- memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
- m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
-
- return RESULT_OK;
-}
-
-
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
ASDCP::Result_t
LocalEditRate = PDesc.EditRate;
m_PDesc = PDesc;
- Result_t result = JP2K_PDesc_to_MD(m_PDesc);
+ assert(m_Dict);
+ Result_t result = JP2K_PDesc_to_MD(m_PDesc, *m_Dict,
+ (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor,
+ m_EssenceSubDescriptor);
if ( ASDCP_SUCCESS(result) )
{
Result_t MD_to_WriterInfo(MXF::Identification*, WriterInfo&);
Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, WriterInfo&, const Dictionary&);
+
Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
+
+ Result_t MD_to_JP2K_PDesc(const ASDCP::MXF::RGBAEssenceDescriptor& EssenceDescriptor,
+ const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
+ const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
+ ASDCP::JP2K::PictureDescriptor& PDesc);
+
+ Result_t JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
+ const ASDCP::Dictionary& dict,
+ ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor,
+ ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor);
+
Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc);
+
void AddDMScrypt(Partition& HeaderPart, SourcePackage& Package,
WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict);
ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
AESEncContext* Ctx, HMACContext* HMAC);
+
//
class KLReader : public ASDCP::KLVPacket
{
}
};
-
+ //------------------------------------------------------------------------------------------
//
+
//
template <class ClipT>
struct TrackSet
inline Result_t Goto_FINAL() { Goto_body(ST_RUNNING, ST_FINAL); }
};
+ //------------------------------------------------------------------------------------------
//
+
//
template <class HeaderType>
class TrackFileWriter
default_md_object_init();
}
- virtual ~TrackFileWriter() {}
+ virtual ~TrackFileWriter() {
+ Close();
+ }
const MXF::RIP& GetRIP() const { return m_RIP; }
m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
}
- //
- Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC)
- {
- return Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
- m_StreamOffset, FrameBuf, EssenceUL, Ctx, HMAC);
- }
-
//
void Close()
{
}/// namespace MXF
+ //------------------------------------------------------------------------------------------
+ //
+
//
class h__ASDCPReader : public MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>
{
h__ASDCPWriter(const Dictionary&);
virtual ~h__ASDCPWriter();
- Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
-
// all the above for a single source clip
Result_t WriteASDCPHeader(const std::string& PackageLabel, const UL& WrappingUL,
const std::string& TrackName, const UL& EssenceUL,
const UL& DataDefinition, const MXF::Rational& EditRate,
ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
+ Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
+ Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
+ AESEncContext* Ctx, HMACContext* HMAC);
Result_t WriteASDCPFooter();
};
// slurp up the remainder of the footer
ui32_t read_count = 0;
- if ( ASDCP_SUCCESS(result) )
+ if ( ASDCP_SUCCESS(result) && IndexByteCount > 0 )
{
assert (IndexByteCount <= 0xFFFFFFFFL);
// At this point, m_FooterData may not have been initialized
// However, if IndexByteCount is zero then the capacity
// doesn't change and the data pointer is not set.
result = m_FooterData.Capacity((ui32_t) IndexByteCount);
- }
- if ( ASDCP_SUCCESS(result) && m_FooterData.Data() )
- result = Reader.Read(m_FooterData.Data(), m_FooterData.Capacity(), &read_count);
+ if ( ASDCP_SUCCESS(result) )
+ result = Reader.Read(m_FooterData.Data(), m_FooterData.Capacity(), &read_count);
- if ( ASDCP_SUCCESS(result) && read_count != m_FooterData.Capacity() )
- {
- DefaultLogSink().Error("Short read of footer partition: got %u, expecting %u\n",
- read_count, m_FooterData.Capacity());
- return RESULT_FAIL;
- }
- else if( ASDCP_SUCCESS(result) && !m_FooterData.Data() )
- {
- DefaultLogSink().Error( "Buffer for footer partition not created: IndexByteCount = %u\n",
- IndexByteCount );
- return RESULT_FAIL;
+ if ( ASDCP_SUCCESS(result) && read_count != m_FooterData.Capacity() )
+ {
+ DefaultLogSink().Error("Short read of footer partition: got %u, expecting %u\n",
+ read_count, m_FooterData.Capacity());
+ return RESULT_FAIL;
+ }
+ else if( ASDCP_SUCCESS(result) && !m_FooterData.Data() )
+ {
+ DefaultLogSink().Error( "Buffer for footer partition not created: IndexByteCount = %u\n",
+ IndexByteCount );
+ return RESULT_FAIL;
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ result = InitFromBuffer(m_FooterData.RoData(), m_FooterData.Capacity());
}
- if ( ASDCP_SUCCESS(result) )
- result = InitFromBuffer(m_FooterData.RoData(), m_FooterData.Capacity());
-
return result;
}
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-ACLOCAL_AMFLAGS = -I m4
-
# Allow for configure's changes to this makefile
AM_CPPFLAGS =
AM_LDFLAGS =
nodist_include_HEADERS = TimedText_Transform.h
endif
-if AS_02_USE
+if USE_AS_02
include_HEADERS += AS_02.h
endif
lib_LTLIBRARIES = libkumu.la libasdcp.la
-if AS_02_USE
+if USE_AS_02
lib_LTLIBRARIES += libas02.la
endif
libasdcp_la_LIBADD = libkumu.la
libasdcp_la_CPPFLAGS = -DASDCP_PLATFORM=\"@host@\"
-if AS_02_USE
+if USE_AS_02
# sources for as-02 library
libas02_la_SOURCES = \
AS_02.h \
- AS_02_MXF.cpp \
- AS_02_JP2K.cpp \
- AS_02_PCM.cpp \
+ AS_02_internal.h \
h__02_Reader.cpp \
h__02_Writer.cpp \
- AS_02_internal.h
+ AS_02_JP2K.cpp \
+ AS_02_PCM.cpp
libas02_la_LDFLAGS = -release @VERSION@
libas02_la_LIBADD = libasdcp.la libkumu.la
j2c-test blackwave klvwalk wavesplit \
kmfilegen kmrandgen kmuuidgen
-if AS_02_USE
+if USE_AS_02
bin_PROGRAMS += \
as-02-wrap \
as-02-unwrap
j2c_test_SOURCES = j2c-test.cpp
j2c_test_LDADD = libasdcp.la
-if AS_02_USE
+if USE_AS_02
as_02_wrap_SOURCES = as-02-wrap.cpp
as_02_wrap_LDADD = libas02.la
\n\
%s [-a <uuid>] [-b <buffer-size>] [-C <UL>] [-d <duration>]\n\
[-e|-E] [-f <start-frame>] [-j <key-id-string>] [-k <key-string>]\n\
- [-M] [-p <n>/<d>] [-v] [-W]\n\
+ [-M] [-p <n>/<d>] [-s <seconds>] [-v] [-W]\n\
[-z|-Z] <input-file>+ <output-file>\n\n",
PROGRAM_NAME, PROGRAM_NAME);
-d <duration> - Number of frames to process, default all\n\
-f <start-frame> - Starting frame number, default 0\n\
-p <n>/<d> - Edit Rate of the output file. 24/1 is the default\n\
+ -s <seconds> - Duration of a frame-wrapped partition (default 60)\n\
-v - Verbose, prints informative messages to stderr\n\
-W - Read input file only, do not write source file\n\
-z - Fail if j2c inputs have unequal parameters (default)\n\
error_flag(true), key_flag(false), key_id_flag(false), asset_id_flag(false),
encrypt_header_flag(true), write_hmac(true), verbose_flag(false), fb_dump_size(0),
no_write_flag(false), version_flag(false), help_flag(false), start_frame(0),
- duration(0xffffffff), j2c_pedantic(true), fb_size(FRAME_BUFFER_SIZE),
+ duration(0xffffffff), j2c_pedantic(true), edit_rate(30,1), fb_size(FRAME_BUFFER_SIZE),
show_ul_values(false), index_strategy(AS_02::IS_FOLLOW), partition_space(60)
{
memset(key_value, 0, KeyLen);
edit_rate.Denominator = 1;
break;
+ case 's':
+ TEST_EXTRA_ARG(i, 's');
+ partition_space = abs(atoi(argv[i]));
+ break;
+
case 'V': version_flag = true; break;
case 'v': verbose_flag = true; break;
case 'W': no_write_flag = true; break;
\brief MXF file reader base class
*/
+#define DEFAULT_MD_DECL
#include "AS_02_internal.h"
using namespace ASDCP;
AS_02::h__AS02Reader::~h__AS02Reader() {}
-#if 0
-//
-AS_02::h__AS02Reader::h__Reader(const Dictionary& d) :
- m_HeaderPart(m_Dict), m_IndexAccess(m_Dict), m_Dict(&d), m_EssenceStart(0)
+
+// AS-DCP method of opening an MXF file for read
+Result_t
+AS_02::h__AS02Reader::OpenMXFRead(const char* filename)
+{
+ Result_t result = ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::OpenMXFRead(filename);
+
+ if ( KM_SUCCESS(result) )
+ result = ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::InitInfo();
+
+ if( KM_SUCCESS(result) )
+ {
+ //
+ InterchangeObject* Object;
+ m_Info.LabelSetType = LS_MXF_SMPTE;
+
+ if ( ! m_HeaderPart.OperationalPattern.ExactMatch(SMPTE_390_OPAtom_Entry().ul) )
+ {
+ char strbuf[IdentBufferLen];
+ const MDDEntry* Entry = m_Dict->FindUL(m_HeaderPart.OperationalPattern.Value());
+
+ if ( Entry == 0 )
+ {
+ DefaultLogSink().Warn("Operational pattern is not OP-1a: %s\n",
+ m_HeaderPart.OperationalPattern.EncodeString(strbuf, IdentBufferLen));
+ }
+ else
+ {
+ DefaultLogSink().Warn("Operational pattern is not OP-1a: %s\n", Entry->name);
+ }
+ }
+
+ //
+ if ( m_RIP.PairArray.front().ByteOffset != 0 )
+ {
+ DefaultLogSink().Error("First Partition in RIP is not at offset 0.\n");
+ result = RESULT_FORMAT;
+ }
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ m_HeaderPart.BodyOffset = m_File.Tell();
+
+ result = m_File.Seek(m_HeaderPart.FooterPartition);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ m_IndexAccess.m_Lookup = &m_HeaderPart.m_Primer;
+ result = m_IndexAccess.InitFromFile(m_File);
+ }
+ }
+
+ m_File.Seek(m_HeaderPart.BodyOffset);
+ return result;
+}
+
+// AS-DCP method of reading a plaintext or encrypted frame
+Result_t
+AS_02::h__AS02Reader::ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
+ const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
{
- m_pCurrentIndexPartition = 0;
- //// start_pos = 0;
+ return ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::ReadEKLVFrame(m_HeaderPart, FrameNum, FrameBuf,
+ EssenceUL, Ctx, HMAC);
}
-AS_02::h__AS02Reader::~h__Reader()
+Result_t
+AS_02::h__AS02Reader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
+ i8_t& temporalOffset, i8_t& keyFrameOffset)
{
- std::vector<Partition*>::iterator bli = m_BodyPartList.begin();
- for ( ; bli != m_BodyPartList.end(); bli++ ){
- delete(*bli);
- *bli = 0;
- }
- Close();
+ return ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::LocateFrame(m_HeaderPart, FrameNum,
+ streamOffset, temporalOffset, keyFrameOffset);
}
-#endif
-//------------------------------------------------------------------------------------------
-//
//
// end h__02_Reader.cpp
using namespace ASDCP;
using namespace ASDCP::MXF;
+static const ui32_t CBRIndexEntriesPerSegment = 5000;
+
+
+//------------------------------------------------------------------------------------------
+//
+
+AS_02::AS02IndexWriter::AS02IndexWriter(const ASDCP::Dictionary*& d) :
+ Partition(d), m_CurrentSegment(0), m_BytesPerEditUnit(0), m_Dict(d), m_ECOffset(0), m_Lookup(0)
+{
+ BodySID = 0;
+ IndexSID = 129;
+}
+
+AS_02::AS02IndexWriter::~AS02IndexWriter() {}
+
+//
+Result_t
+AS_02::AS02IndexWriter::WriteToFile(Kumu::FileWriter& Writer)
+{
+ // UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
+
+ assert(m_Dict);
+ ASDCP::FrameBuffer FooterBuffer;
+ ui32_t footer_size = m_PacketList->m_List.size() * MaxIndexSegmentSize; // segment-count * max-segment-size
+ Result_t result = FooterBuffer.Capacity(footer_size);
+ ui32_t iseg_count = 0;
+
+ if ( m_CurrentSegment != 0 )
+ {
+ m_CurrentSegment->IndexDuration = m_CurrentSegment->IndexEntryArray.size();
+ m_CurrentSegment = 0;
+ }
+
+ std::list<InterchangeObject*>::iterator pl_i = m_PacketList->m_List.begin();
+ for ( ; pl_i != m_PacketList->m_List.end() && ASDCP_SUCCESS(result); pl_i++ )
+ {
+ if ( (*pl_i)->IsA(OBJ_TYPE_ARGS(IndexTableSegment)) )
+ {
+ iseg_count++;
+ IndexTableSegment* Segment = (IndexTableSegment*)(*pl_i);
+
+ if ( m_BytesPerEditUnit != 0 )
+ {
+ if ( iseg_count != 1 )
+ return RESULT_STATE;
+
+ /// Segment->IndexDuration = duration;
+ }
+ }
+
+ InterchangeObject* object = *pl_i;
+ object->m_Lookup = m_Lookup;
+
+ ASDCP::FrameBuffer WriteWrapper;
+ WriteWrapper.SetData(FooterBuffer.Data() + FooterBuffer.Size(),
+ FooterBuffer.Capacity() - FooterBuffer.Size());
+ result = object->WriteToBuffer(WriteWrapper);
+ FooterBuffer.Size(FooterBuffer.Size() + WriteWrapper.Size());
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ IndexByteCount = FooterBuffer.Size();
+ UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
+ result = Partition::WriteToFile(Writer, body_ul);
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ui32_t write_count = 0;
+ result = Writer.Write(FooterBuffer.RoData(), FooterBuffer.Size(), &write_count);
+ assert(write_count == FooterBuffer.Size());
+ }
+
+ return result;
+}
+
+//
+void
+AS_02::AS02IndexWriter::ResetCBR(Kumu::fpos_t offset)
+{
+ m_ECOffset = offset;
+
+ std::list<InterchangeObject*>::iterator i;
+
+ for ( i = m_PacketList->m_List.begin(); i != m_PacketList->m_List.end(); ++i )
+ {
+ delete *i;
+ }
+
+ m_PacketList->m_List.clear();
+}
+
+//
+void
+AS_02::AS02IndexWriter::Dump(FILE* stream)
+{
+ if ( stream == 0 )
+ stream = stderr;
+
+ Partition::Dump(stream);
+
+ std::list<InterchangeObject*>::iterator i = m_PacketList->m_List.begin();
+ for ( ; i != m_PacketList->m_List.end(); i++ )
+ (*i)->Dump(stream);
+}
+
+//
+ui32_t
+AS_02::AS02IndexWriter::GetDuration() const
+{
+ ui32_t duration;
+ std::list<InterchangeObject*>::const_iterator i;
+
+ for ( i = m_PacketList->m_List.begin(); i != m_PacketList->m_List.end(); ++i )
+ {
+ if ( (*i)->IsA(OBJ_TYPE_ARGS(IndexTableSegment)) )
+ {
+ IndexTableSegment& Segment = *(IndexTableSegment*)*i;
+ duration += Segment.IndexDuration;
+ }
+ }
+
+ return duration;
+}
+
+//
+void
+AS_02::AS02IndexWriter::SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const ASDCP::Rational& Rate)
+{
+ assert(lookup);
+ m_Lookup = lookup;
+ m_BytesPerEditUnit = size;
+ m_EditRate = Rate;
+
+ IndexTableSegment* Index = new IndexTableSegment(m_Dict);
+ AddChildObject(Index);
+ Index->EditUnitByteCount = m_BytesPerEditUnit;
+ Index->IndexEditRate = Rate;
+}
+
+//
+void
+AS_02::AS02IndexWriter::SetIndexParamsVBR(IPrimerLookup* lookup, const ASDCP::Rational& Rate, Kumu::fpos_t offset)
+{
+ assert(lookup);
+ m_Lookup = lookup;
+ m_BytesPerEditUnit = 0;
+ m_EditRate = Rate;
+ m_ECOffset = offset;
+}
//
-AS_02::h__AS02Writer::h__AS02Writer(const ASDCP::Dictionary& d) : ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>(d) {}
+void
+AS_02::AS02IndexWriter::PushIndexEntry(const IndexTableSegment::IndexEntry& Entry)
+{
+ if ( m_BytesPerEditUnit != 0 ) // are we CBR? that's bad
+ {
+ DefaultLogSink().Error("Call to PushIndexEntry() failed: index is CBR\n");
+ return;
+ }
+
+ // do we have an available segment?
+ if ( m_CurrentSegment == 0 )
+ { // no, set up a new segment
+ m_CurrentSegment = new IndexTableSegment(m_Dict);
+ assert(m_CurrentSegment);
+ AddChildObject(m_CurrentSegment);
+ m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry());
+ m_CurrentSegment->IndexEditRate = m_EditRate;
+ m_CurrentSegment->IndexStartPosition = 0;
+ }
+ else if ( m_CurrentSegment->IndexEntryArray.size() >= CBRIndexEntriesPerSegment )
+ { // no, this one is full, start another
+ m_CurrentSegment->IndexDuration = m_CurrentSegment->IndexEntryArray.size();
+ ui64_t StartPosition = m_CurrentSegment->IndexStartPosition + m_CurrentSegment->IndexDuration;
+
+ m_CurrentSegment = new IndexTableSegment(m_Dict);
+ assert(m_CurrentSegment);
+ AddChildObject(m_CurrentSegment);
+ m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry());
+ m_CurrentSegment->IndexEditRate = m_EditRate;
+ m_CurrentSegment->IndexStartPosition = StartPosition;
+ }
+
+ m_CurrentSegment->IndexEntryArray.push_back(Entry);
+}
+
+
+//------------------------------------------------------------------------------------------
+//
+
+//
+AS_02::h__AS02Writer::h__AS02Writer(const ASDCP::Dictionary& d) : ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>(d),
+ m_IndexWriter(m_Dict), m_PartitionSpace(0),
+ m_IndexStrategy(AS_02::IS_FOLLOW) {}
+
AS_02::h__AS02Writer::~h__AS02Writer() {}
//
Result_t
AS_02::h__AS02Writer::WriteAS02Header(const std::string& PackageLabel, const ASDCP::UL& WrappingUL,
- const std::string& TrackName, const ASDCP::UL& EssenceUL,
- const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
- ui32_t TCFrameRate, ui32_t BytesPerEditUnit)
+ const std::string& TrackName, const ASDCP::UL& EssenceUL, const ASDCP::UL& DataDefinition,
+ const ASDCP::Rational& EditRate, ui32_t TCFrameRate, ui32_t BytesPerEditUnit)
{
+ if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 )
+ {
+ DefaultLogSink().Error("Non-zero edit-rate reqired.\n");
+ return RESULT_PARAM;
+ }
+
InitHeader();
+
AddSourceClip(EditRate, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel);
AddEssenceDescriptor(WrappingUL);
+ m_RIP.PairArray.push_back(RIP::Pair(0, 0)); // Header partition RIP entry
+ m_IndexWriter.OperationalPattern = m_HeaderPart.OperationalPattern;
Result_t result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
- //use the FrameRate for the indexing; initialize the SID counters
- /// m_CurrentBodySID = 0;
- /// m_CurrentIndexSID = 0;
- m_PartitionSpace = m_PartitionSpace * TCFrameRate; ///// TODO ????
+ if ( ASDCP_SUCCESS(result) )
+ {
+ m_PartitionSpace *= ceil(EditRate.Quotient()); // convert seconds to edit units
+ Kumu::fpos_t ECoffset = m_File.Tell();
+ m_IndexWriter.IndexSID = 129;
+
+ if ( BytesPerEditUnit == 0 )
+ {
+ m_IndexWriter.SetIndexParamsVBR(&m_HeaderPart.m_Primer, EditRate, ECoffset);
+ }
+ else
+ {
+ m_IndexWriter.SetIndexParamsCBR(&m_HeaderPart.m_Primer, BytesPerEditUnit, EditRate);
+ }
+
+ UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
+ Partition body_part(m_Dict);
+ body_part.BodySID = 1;
+ body_part.OperationalPattern = m_HeaderPart.OperationalPattern;
+ body_part.ThisPartition = m_File.Tell();
+ result = body_part.WriteToFile(m_File, body_ul);
+ m_RIP.PairArray.push_back(RIP::Pair(1, body_part.ThisPartition)); // Second RIP Entry
+
+ }
return result;
}
-
+
+//
+Result_t
+AS_02::h__AS02Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC)
+{
+ Result_t result = Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
+ m_StreamOffset, FrameBuf, EssenceUL, Ctx, HMAC);
+
+ if ( m_FramesWritten > 0 && ( m_FramesWritten % m_PartitionSpace ) == 0 )
+ {
+ m_IndexWriter.ThisPartition = m_File.Tell();
+ m_IndexWriter.WriteToFile(m_File);
+ m_RIP.PairArray.push_back(RIP::Pair(129, m_IndexWriter.ThisPartition));
+
+ UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
+ Partition body_part(m_Dict);
+ body_part.BodySID = 1;
+ body_part.OperationalPattern = m_HeaderPart.OperationalPattern;
+ body_part.ThisPartition = m_File.Tell();
+ result = body_part.WriteToFile(m_File, body_ul);
+ m_RIP.PairArray.push_back(RIP::Pair(1, body_part.ThisPartition));
+ m_IndexWriter.ResetCBR(m_File.Tell());
+ }
+
+ return result;
+}
+
+// standard method of writing the header and footer of a completed MXF file
+//
+Result_t
+AS_02::h__AS02Writer::WriteAS02Footer()
+{
+
+ if ( m_IndexWriter.GetDuration() > 0 )
+ {
+ m_IndexWriter.ThisPartition = m_File.Tell();
+ m_IndexWriter.WriteToFile(m_File);
+ m_RIP.PairArray.push_back(RIP::Pair(129, m_IndexWriter.ThisPartition));
+ }
+
+ // update all Duration properties
+ ASDCP::MXF::Partition footer_part(m_Dict);
+ DurationElementList_t::iterator dli = m_DurationUpdateList.begin();
+
+ for (; dli != m_DurationUpdateList.end(); ++dli )
+ {
+ **dli = m_FramesWritten;
+ }
+
+ m_EssenceDescriptor->ContainerDuration = m_FramesWritten;
+ footer_part.PreviousPartition = m_RIP.PairArray.back().ByteOffset;
+
+ Kumu::fpos_t here = m_File.Tell();
+ m_RIP.PairArray.push_back(RIP::Pair(0, here)); // Last RIP Entry
+ m_HeaderPart.FooterPartition = here;
+
+ assert(m_Dict);
+ footer_part.OperationalPattern = m_HeaderPart.OperationalPattern;
+ footer_part.EssenceContainers = m_HeaderPart.EssenceContainers;
+ footer_part.FooterPartition = here;
+ footer_part.ThisPartition = here;
+
+ UL footer_ul(m_Dict->ul(MDD_CompleteFooter));
+ Result_t result = footer_part.WriteToFile(m_File, footer_ul);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = m_RIP.WriteToFile(m_File);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = m_File.Seek(0);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ASDCP::MXF::Array<ASDCP::MXF::RIP::Pair>::const_iterator i = m_RIP.PairArray.begin();
+ ui64_t header_byte_count = m_HeaderPart.HeaderByteCount;
+ ui64_t previous_partition = 0;
+
+ for ( i = m_RIP.PairArray.begin(); ASDCP_SUCCESS(result) && i != m_RIP.PairArray.end(); ++i )
+ {
+ if ( i->BodySID == 0 )
+ continue;
+
+ result = m_File.Seek(i->ByteOffset);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ASDCP::MXF::Partition plain_part(m_Dict);
+ plain_part.InitFromFile(m_File);
+ plain_part.PreviousPartition = previous_partition;
+ plain_part.FooterPartition = footer_part.ThisPartition;
+ previous_partition = plain_part.ThisPartition;
+ result = m_File.Seek(i->ByteOffset);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ UL tmp_ul = plain_part.GetUL();
+ result = plain_part.WriteToFile(m_File, tmp_ul);
+ }
+ }
+ }
+ }
+
+ m_File.Close();
+ return result;
+}
+
//
// end h__02_Writer.cpp
return result;
}
-
+//
+Result_t
+ASDCP::h__ASDCPWriter::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
+ AESEncContext* Ctx, HMACContext* HMAC)
+{
+ return Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
+ m_StreamOffset, FrameBuf, EssenceUL, Ctx, HMAC);
+}
// standard method of writing the header and footer of a completed MXF file
//
usage(FILE* stream = stdout)
{
fprintf(stream, "\
-USAGE: %s [-r] [-v] <input-file> [<input-file2> ...]\n\
+USAGE: %s [-r|-p] [-v] <input-file> [<input-file2> ...]\n\
\n\
%s [-h|-help] [-V]\n\
\n\
-h | -help - Show help\n\
- -r - When KLV data is an MXF OPAtom file, display OPAtom headers\n\
+ -r - When KLV data is an MXF OPAtom or OP 1a file, display headers\n\
+ -p - Display partition headers by walking the RIP\n\
-v - Verbose. Prints informative messages to stderr\n\
-V - Show version information\n\
\n\
bool help_flag; // true if the help display option was selected
bool verbose_flag; // true if the informative messages option was selected
bool read_mxf_flag; // true if the -r option was selected
+ bool walk_parts_flag; // true if the -p option was selected
FileList_t inFileList; // File to operate on
CommandOptions(int argc, const char** argv) :
- error_flag(true), version_flag(false), help_flag(false), verbose_flag(false), read_mxf_flag(false)
+ error_flag(true), version_flag(false), help_flag(false),
+ verbose_flag(false), read_mxf_flag(false), walk_parts_flag(false)
{
for ( int i = 1; i < argc; i++ )
{
{
case 'h': help_flag = true; break;
case 'r': read_mxf_flag = true; break;
+ case 'p': walk_parts_flag = true; break;
case 'V': version_flag = true; break;
case 'v': verbose_flag = true; break;
if ( ASDCP_SUCCESS(result) )
RIP.Dump(stdout);
}
+ else if ( Options.walk_parts_flag )
+ {
+ Kumu::FileReader Reader;
+ const Dictionary* Dict = &DefaultCompositeDict();
+ ASDCP::MXF::OP1aHeader Header(Dict);
+ ASDCP::MXF::RIP RIP(Dict);
+
+ result = Reader.OpenRead((*fi).c_str());
+
+ if ( ASDCP_SUCCESS(result) )
+ result = MXF::SeekToRIP(Reader);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ result = RIP.InitFromFile(Reader);
+ ui32_t test_s = RIP.PairArray.size();
+
+ if ( ASDCP_FAILURE(result) )
+ {
+ DefaultLogSink().Error("File contains no RIP\n");
+ result = RESULT_OK;
+ }
+ else if ( RIP.PairArray.empty() )
+ {
+ DefaultLogSink().Error("RIP contains no Pairs.\n");
+ }
+
+ Reader.Seek(0);
+ }
+ else
+ {
+ DefaultLogSink().Error("ASDCP::h__Reader::OpenMXFRead, SeekToRIP failed\n");
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ MXF::Array<MXF::RIP::Pair>::const_iterator i;
+ for ( i = RIP.PairArray.begin(); i != RIP.PairArray.end(); ++i )
+ {
+ Reader.Seek(i->ByteOffset);
+ MXF::Partition plain_part(Dict);
+ plain_part.InitFromFile(Reader);
+
+ if ( plain_part.ThisPartition != i->ByteOffset )
+ {
+ DefaultLogSink().Error("ThisPartition value error: wanted=%qu, got=%qu\n",
+ plain_part.ThisPartition, i->ByteOffset);
+ }
+
+ plain_part.Dump();
+ }
+ }
+ }
else // dump klv
{
Kumu::FileReader Reader;