Example #1
0
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
Result_t
AS_02::JP2K::MXFWriter::h__Writer::OpenWrite(const std::string& filename,
					     ASDCP::MXF::FileDescriptor* essence_descriptor,
					     ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
					     const AS_02::IndexStrategy_t& IndexStrategy,
					     const ui32_t& PartitionSpace_sec, const ui32_t& HeaderSize)
{
  if ( ! m_State.Test_BEGIN() )
    {
      KM_RESULT_STATE_HERE();
	return RESULT_STATE;
    }

  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.c_str());

  if ( KM_SUCCESS(result) )
    {
      m_IndexStrategy = IndexStrategy;
      m_PartitionSpace = PartitionSpace_sec; // later converted to edit units by SetSourceStream()
      m_HeaderSize = HeaderSize;

      if ( essence_descriptor->GetUL() != UL(m_Dict->ul(MDD_RGBAEssenceDescriptor))
	   && essence_descriptor->GetUL() != UL(m_Dict->ul(MDD_CDCIEssenceDescriptor)) )
	{
	  DefaultLogSink().Error("Essence descriptor is not a RGBAEssenceDescriptor or CDCIEssenceDescriptor.\n");
	  essence_descriptor->Dump();
	  return RESULT_AS02_FORMAT;
	}

      m_EssenceDescriptor = essence_descriptor;

      ASDCP::MXF::InterchangeObject_list_t::iterator i;
      for ( i = essence_sub_descriptor_list.begin(); i != essence_sub_descriptor_list.end(); ++i )
	{
	  if ( (*i)->GetUL() != UL(m_Dict->ul(MDD_JPEG2000PictureSubDescriptor)) )
	    {
	      DefaultLogSink().Error("Essence sub-descriptor is not a JPEG2000PictureSubDescriptor.\n");
	      (*i)->Dump();
	    }

	  m_EssenceSubDescriptorList.push_back(*i);
	  GenRandomValue((*i)->InstanceUID);
	  m_EssenceDescriptor->SubDescriptors.push_back((*i)->InstanceUID);
	  *i = 0; // parent will only free the ones we don't keep
	}

      result = m_State.Goto_INIT();
    }

  return result;
}
ASDCP::Result_t
AS_02::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedTextDescriptor const& TDesc)
{
  if ( ! m_State.Test_INIT() )
    {
      KM_RESULT_STATE_HERE();
      return RESULT_STATE;
    }

  assert(m_Dict);
  m_TDesc = TDesc;

  Result_t result = TimedText_TDesc_to_MD(m_TDesc);

  if ( KM_SUCCESS(result) )
    {
      ResourceList_t::const_iterator i;
      for ( i = m_TDesc.ResourceList.begin() ; i != m_TDesc.ResourceList.end(); ++i )
	{
	  TimedTextResourceSubDescriptor* resourceSubdescriptor = new TimedTextResourceSubDescriptor(m_Dict);
	  GenRandomValue(resourceSubdescriptor->InstanceUID);
	  resourceSubdescriptor->AncillaryResourceID.Set((*i).ResourceID);
	  resourceSubdescriptor->MIMEMediaType = MIME2str((*i).Type);
	  resourceSubdescriptor->EssenceStreamID = m_EssenceStreamID++;
	  m_EssenceSubDescriptorList.push_back((FileDescriptor*)resourceSubdescriptor);
	  m_EssenceDescriptor->SubDescriptors.push_back(resourceSubdescriptor->InstanceUID);

	  // 72 == sizeof K, L, instanceuid, uuid + sizeof int32 + tag/len * 4
	  m_HeaderSize += ( resourceSubdescriptor->MIMEMediaType.ArchiveLength() * 2 /*ArchiveLength is broken*/ ) + 72;
	}
    }
  
  if ( KM_SUCCESS(result) )
    {
      result = WriteAS02Header(TIMED_TEXT_PACKAGE_LABEL, UL(m_Dict->ul(MDD_TimedTextWrappingClip)),
			       "Data Track", UL(m_EssenceUL), UL(m_Dict->ul(MDD_TimedTextEssence)),
			       TDesc.EditRate, derive_timecode_rate_from_edit_rate(TDesc.EditRate));
    }
 
  if ( KM_SUCCESS(result) )
    {
      this->m_IndexWriter.SetPrimerLookup(&this->m_HeaderPart.m_Primer);
    }

  if ( KM_SUCCESS(result) )
    {
      memcpy(m_EssenceUL, m_Dict->ul(MDD_TimedTextEssence), SMPTE_UL_LENGTH);
      m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
      result = m_State.Goto_READY();
    }

  return result;
}
ASDCP::Result_t
ASDCP::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedTextDescriptor const& TDesc)
{
  if ( ! m_State.Test_INIT() )
    return RESULT_STATE;

  m_TDesc = TDesc;
  ResourceList_t::const_iterator ri;
  Result_t result = TimedText_TDesc_to_MD(m_TDesc);

  for ( ri = m_TDesc.ResourceList.begin() ; ri != m_TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
    {
      TimedTextResourceSubDescriptor* resourceSubdescriptor = new TimedTextResourceSubDescriptor(m_Dict);
      GenRandomValue(resourceSubdescriptor->InstanceUID);
      resourceSubdescriptor->AncillaryResourceID.Set((*ri).ResourceID);
      resourceSubdescriptor->MIMEMediaType = MIME2str((*ri).Type);
      resourceSubdescriptor->EssenceStreamID = m_EssenceStreamID++;
      m_EssenceSubDescriptorList.push_back((FileDescriptor*)resourceSubdescriptor);
      m_EssenceDescriptor->SubDescriptors.push_back(resourceSubdescriptor->InstanceUID);

      // 72 == sizeof K, L, instanceuid, uuid + sizeof int32 + tag/len * 4
      m_HeaderSize += ( resourceSubdescriptor->MIMEMediaType.ArchiveLength() * 2 /*ArchiveLength is broken*/ ) + 72;
    }

  m_EssenceStreamID = 10;
  assert(m_Dict);

  if ( ASDCP_SUCCESS(result) )
    {
      InitHeader();
      AddDMSegment(m_TDesc.EditRate, 24, TIMED_TEXT_DEF_LABEL,
		   UL(m_Dict->ul(MDD_DataDataDef)), TIMED_TEXT_PACKAGE_LABEL);

      AddEssenceDescriptor(UL(m_Dict->ul(MDD_TimedTextWrapping)));

      result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
      
      if ( KM_SUCCESS(result) )
	result = CreateBodyPart(m_TDesc.EditRate);
    }

  if ( ASDCP_SUCCESS(result) )
    {
      memcpy(m_EssenceUL, m_Dict->ul(MDD_TimedTextEssence), SMPTE_UL_LENGTH);
      m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
      result = m_State.Goto_READY();
    }

  return result;
}
ASDCP::Result_t
ASDCP::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedTextDescriptor const& TDesc)
{
  if ( ! m_State.Test_INIT() )
    return RESULT_STATE;

  m_TDesc = TDesc;
  ResourceList_t::const_iterator ri;
  Result_t result = TimedText_TDesc_to_MD(m_TDesc);

  for ( ri = m_TDesc.ResourceList.begin() ; ri != m_TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
    {
      TimedTextResourceSubDescriptor* resourceSubdescriptor = new TimedTextResourceSubDescriptor(m_Dict);
      GenRandomValue(resourceSubdescriptor->InstanceUID);
      resourceSubdescriptor->AncillaryResourceID.Set((*ri).ResourceID);
      resourceSubdescriptor->MIMEMediaType = MIME2str((*ri).Type);
      resourceSubdescriptor->EssenceStreamID = m_EssenceStreamID++;
      m_EssenceSubDescriptorList.push_back((FileDescriptor*)resourceSubdescriptor);
      m_EssenceDescriptor->SubDescriptors.push_back(resourceSubdescriptor->InstanceUID);

      // 72 == sizeof K, L, instanceuid, uuid + sizeof int32 + tag/len * 4
      m_HeaderSize += ( resourceSubdescriptor->MIMEMediaType.ArchiveLength() * 2 /*ArchiveLength is broken*/ ) + 72;
    }

  m_EssenceStreamID = 10;
  assert(m_Dict);

  if ( ASDCP_SUCCESS(result) )
    {
      InitHeader(MXFVersion_2004);

      // First RIP Entry
      if ( m_Info.LabelSetType == LS_MXF_SMPTE )  // ERK
	{
	  m_RIP.PairArray.push_back(RIP::PartitionPair(0, 0)); // 3-part, no essence in header
	}
      else
	{
	  DefaultLogSink().Error("Unable to write Interop timed-text MXF file.  Use SMPTE DCP options instead.\n");
	  return RESULT_FORMAT;
	}

      // timecode rate and essence rate are the same
      AddSourceClip(m_TDesc.EditRate, m_TDesc.EditRate, derive_timecode_rate_from_edit_rate(m_TDesc.EditRate),
		    TIMED_TEXT_DEF_LABEL, m_EssenceUL, UL(m_Dict->ul(MDD_DataDataDef)), TIMED_TEXT_PACKAGE_LABEL);

      AddEssenceDescriptor(UL(m_Dict->ul(MDD_TimedTextWrappingClip)));
      result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
      
      if ( KM_SUCCESS(result) )
	result = CreateBodyPart(m_TDesc.EditRate);
    }

  if ( ASDCP_SUCCESS(result) )
    {
      memcpy(m_EssenceUL, m_Dict->ul(MDD_TimedTextEssence), SMPTE_UL_LENGTH);
      m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
      result = m_State.Goto_READY();
    }

  return result;
}
Example #5
0
// all the above for a single source clip
Result_t
AS_02::PHDR::MXFWriter::h__Writer::WritePHDRHeader(const std::string& PackageLabel, const ASDCP::UL& WrappingUL,
        const std::string& TrackName, const ASDCP::UL& EssenceUL,
        const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
        const ui32_t& TCFrameRate)
{
    if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 )
    {
        DefaultLogSink().Error("Non-zero edit-rate reqired.\n");
        return RESULT_PARAM;
    }

    InitHeader();

    AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel);

    // add metadata track
    TrackSet<SourceClip> metdata_track =
        CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage,
                MD_DEF_LABEL, EditRate,
                UL(m_Dict->ul(MDD_PHDRImageMetadataItem)),
                3 /* track id */, m_Dict);

    metdata_track.Sequence->Duration.set_has_value();
    m_DurationUpdateList.push_back(&(metdata_track.Sequence->Duration.get()));
    // Consult ST 379:2004 Sec. 6.3, "Element to track relationship" to see where "12" comes from.
    metdata_track.Track->TrackNumber = KM_i32_BE(Kumu::cp2i<ui32_t>((UL(m_MetadataUL).Value() + 12)));

    metdata_track.Clip = new SourceClip(m_Dict);
    m_HeaderPart.AddChildObject(metdata_track.Clip);
    metdata_track.Sequence->StructuralComponents.push_back(metdata_track.Clip->InstanceUID);
    metdata_track.Clip->DataDefinition = UL(m_Dict->ul(MDD_PHDRImageMetadataWrappingFrame));

    // for now we do not allow setting this value, so all files will be 'original'
    metdata_track.Clip->SourceTrackID = 0;
    metdata_track.Clip->SourcePackageID = NilUMID;

    metdata_track.Clip->Duration.set_has_value();
    m_DurationUpdateList.push_back(&(metdata_track.Clip->Duration.get()));

    // add PHDR subdescriptor
    m_MetadataTrackSubDescriptor = new PHDRMetadataTrackSubDescriptor(m_Dict);
    m_EssenceSubDescriptorList.push_back(m_MetadataTrackSubDescriptor);
    GenRandomValue(m_MetadataTrackSubDescriptor->InstanceUID);
    m_EssenceDescriptor->SubDescriptors.push_back(m_MetadataTrackSubDescriptor->InstanceUID);
    m_MetadataTrackSubDescriptor->DataDefinition = UL(m_Dict->ul(MDD_PHDRImageMetadataWrappingFrame));
    m_MetadataTrackSubDescriptor->SourceTrackID = 3;
    m_MetadataTrackSubDescriptor->SimplePayloadSID = 0;

    AddEssenceDescriptor(WrappingUL);

    m_IndexWriter.SetPrimerLookup(&m_HeaderPart.m_Primer);
    m_RIP.PairArray.push_back(RIP::Pair(0, 0)); // Header partition RIP entry
    m_IndexWriter.OperationalPattern = m_HeaderPart.OperationalPattern;
    m_IndexWriter.EssenceContainers = m_HeaderPart.EssenceContainers;

    Result_t result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);

    if ( KM_SUCCESS(result) )
    {
        m_PartitionSpace *= floor( EditRate.Quotient() + 0.5 );  // convert seconds to edit units
        m_ECStart = m_File.Tell();
        m_IndexWriter.IndexSID = 129;

        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.EssenceContainers = m_HeaderPart.EssenceContainers;
        body_part.ThisPartition = m_ECStart;
        result = body_part.WriteToFile(m_File, body_ul);
        m_RIP.PairArray.push_back(RIP::Pair(1, body_part.ThisPartition)); // Second RIP Entry
    }

    return result;
}