Exemplo n.º 1
0
ASDCP::Result_t
ASDCP::MPEG2::Parser::h__Parser::OpenRead(const std::string& filename)
{
  ui32_t read_count = 0;

  Result_t result = m_FileReader.OpenRead(filename);
  
  if ( ASDCP_SUCCESS(result) )
    result = m_FileReader.Read(m_TmpBuffer.Data(), m_TmpBuffer.Capacity(), &read_count);
  
  if ( ASDCP_SUCCESS(result) )
    {
      const byte_t* p = m_TmpBuffer.RoData();

      // the mxflib parser demanded the file start with a sequence header.
      // Since no one complained and that's the easiest thing to implement,
      // I have left it that way. Let me know if you want to be able to
      // locate the first GOP in the stream.
      ui32_t i = 0;
      while ( p[i] == 0 ) i++;

      if ( i < 2 || p[i] != 1 || ! ( p[i+1] == SEQ_START || p[i+1] == PIC_START ) )
	{
	  DefaultLogSink().Error("Frame buffer does not begin with a PIC or SEQ start code.\n");
	  return RESULT_RAW_FORMAT;
	}

      if ( ASDCP_SUCCESS(result) )
	{
	  m_Parser.SetDelegate(&m_ParamsDelegate);
	  result = m_Parser.Parse(p, read_count);
	}
    }

  if ( ASDCP_SUCCESS(result) )
    {
      ui64_t tmp = m_FileReader.Size() / 65536; // a gross approximation
      m_ParamsDelegate.m_VDesc.ContainerDuration = (ui32_t) tmp;
      m_Parser.SetDelegate(&m_ParserDelegate);
      m_FileReader.Seek(0);
    }

  if ( ASDCP_FAILURE(result) )
    {
      DefaultLogSink().Error("Unable to identify a wrapping mode for the essence in file \"%s\"\n", filename.c_str());
      m_FileReader.Close();
    }

  return result;}
  Result_t OpenReadFrame(const char* filename, FrameBuffer& FB)
  {
    ASDCP_TEST_NULL_STR(filename);
    m_File.Close();
    Result_t result = m_File.OpenRead(filename);

    if ( ASDCP_SUCCESS(result) )
    {
        Kumu::fsize_t file_size = m_File.Size();

        if ( FB.Capacity() < file_size )
        {
            DefaultLogSink().Error("FrameBuf.Capacity: %u frame length: %u\n", FB.Capacity(), (ui32_t)file_size);
            return RESULT_SMALLBUF;
        }
    }

    ui32_t read_count;

    if ( ASDCP_SUCCESS(result) )
        result = m_File.Read(FB.Data(), FB.Capacity(), &read_count);

    if ( ASDCP_SUCCESS(result) )
        FB.Size(read_count);

    return result;
  }
Exemplo n.º 3
0
bool
ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
{
  if ( m_Lookup == 0 )
    {
      DefaultLogSink().Error("No Lookup service\n");
      return false;
    }
  
  TagValue TmpTag;

  if ( m_Lookup->TagForKey(Entry.ul, TmpTag) != RESULT_OK )
    {
      if ( Entry.tag.a == 0 )
	{
	  //	  DefaultLogSink().Debug("No such UL in this TL list: %s (%02x %02x)\n",
	  //				 Entry.name, Entry.tag.a, Entry.tag.b);
	  return false;
	}

      TmpTag = Entry.tag;
    }

  TagMap::iterator e_i = m_ElementMap.find(TmpTag);

  if ( e_i != m_ElementMap.end() )
    {
      m_size = (*e_i).second.first;
      m_capacity = m_size + (*e_i).second.second;
      return true;
    }

  //  DefaultLogSink().Debug("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
  return false;
}
Exemplo n.º 4
0
bool
ASDCP::MXF::UTF16String::Unarchive(Kumu::MemIOReader* Reader)
{
  erase();
  const ui16_t* p = (ui16_t*)Reader->CurrentData();
  ui32_t length = Reader->Remainder() / 2;
  char mb_buf[MB_LEN_MAX+1];

  for ( ui32_t i = 0; i < length; i++ )
    {
      int count = wctomb(mb_buf, KM_i16_BE(p[i]));

      if ( count == -1 )
	{
	  DefaultLogSink().Error("Unable to decode wide character 0x%04hx\n", p[i]);
	  return false;
	}

      assert(count <= MB_LEN_MAX);
      mb_buf[count] = 0;
      this->append(mb_buf);
    }

  Reader->SkipOffset(length*2);
  return true;
}
Exemplo n.º 5
0
void
print_ssl_error()
{
  char err_buf[256];
  unsigned long errval = ERR_get_error();
  DefaultLogSink().Error("OpenSSL: %s\n", ERR_error_string(errval, err_buf));
}
Exemplo n.º 6
0
Result_t
ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::ReadAncillaryResource(const byte_t* uuid, FrameBuffer& FrameBuf,
									     const IResourceResolver& Resolver) const
{
  FrameBuf.AssetID(uuid);
  UUID TmpID(uuid);
  char buf[64];

  ResourceTypeMap_t::const_iterator rmi = m_ResourceTypes.find(TmpID);

  if ( rmi == m_ResourceTypes.end() )
    {
      DefaultLogSink().Error("Unknown ancillary resource id: %s\n", TmpID.EncodeHex(buf, 64));
      return RESULT_RANGE;
    }

  Result_t result = Resolver.ResolveRID(uuid, FrameBuf);

  if ( KM_SUCCESS(result) )
    {
      if ( (*rmi).second == MT_PNG )
	FrameBuf.MIMEType("image/png");
	      
      else if ( (*rmi).second == MT_OPENTYPE )
	FrameBuf.MIMEType("application/x-font-opentype");

      else
	FrameBuf.MIMEType("application/octet-stream");
    }

  return result;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
bool
ASDCP::MXF::UTF16String::Archive(Kumu::MemIOWriter* Writer) const
{
  if ( size() > IdentBufferLen )
    {
      DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
      return false;
    }

  const char* mbp = c_str();
  wchar_t wcp;
  ui32_t remainder = size();
  ui32_t length = size();
  ui32_t i = 0;

  while ( i < length )
    {
      int count = mbtowc(&wcp, mbp+i, remainder);

      if ( count == -1 )
	{
	  DefaultLogSink().Error("Error decoding multi-byte sequence starting at offset %u\n", i);
	  return false;
	}
      else if ( count  == 0 )
	{
	  break;
	}

      bool result = Writer->WriteUi16BE((ui16_t)wcp);

      if ( result == false )
	{
	  DefaultLogSink().Error("No more space in memory IO writer\n");
	  return false;
	}

      i += count;
      remainder -= count;
    }

  return true;
}
Exemplo n.º 9
0
bool
ASDCP::MXF::ISO8String::Archive(Kumu::MemIOWriter* Writer) const
{
  if ( size() > IdentBufferLen )
    {
      DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
      return false;
    }

  return Writer->WriteRaw((const byte_t*)c_str(), size());
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
ASDCP::Result_t
ASDCP::MXF::TLVWriter::WriteTag(const MDDEntry& Entry)
{
  if ( m_Lookup == 0 )
    {
      DefaultLogSink().Error("No Primer object available\n");
      return RESULT_FAIL;
    }

  TagValue TmpTag;

  if ( m_Lookup->InsertTag(Entry, TmpTag) != RESULT_OK )
    {
      DefaultLogSink().Error("No tag for entry %s\n", Entry.name);
      return RESULT_FAIL;
    }

  if ( ! MemIOWriter::WriteUi8(TmpTag.a) ) return RESULT_KLV_CODING(__LINE__, __FILE__);
  if ( ! MemIOWriter::WriteUi8(TmpTag.b) ) return RESULT_KLV_CODING(__LINE__, __FILE__);
  return RESULT_OK;
}
Exemplo n.º 12
0
  inline Result_t Goto_SEQ()
    {
      switch ( m_State )
	{
	case ST_INIT:
	case ST_EXT:
	  m_State = ST_SEQ;
	  return RESULT_OK;
	}
      
      DefaultLogSink().Error("SEQ follows %s\n", StringParserState(m_State));
      return RESULT_STATE;
    }
Exemplo n.º 13
0
  inline Result_t Goto_SLICE()
    {
      switch ( m_State )
	{
	case ST_PIC:
	case ST_EXT:
	  m_State = ST_SLICE;
	  return RESULT_OK;
	}
      
      DefaultLogSink().Error("Slice follows %s\n", StringParserState(m_State));
      return RESULT_STATE;
    }
Exemplo n.º 14
0
Result_t
ASDCP::TimedText::LocalFilenameResolver::OpenRead(const std::string& dirname)
{
  if ( PathIsDirectory(dirname) )
    {
      m_Dirname = dirname;
      return RESULT_OK;
    }

  DefaultLogSink().Error("Path '%s' is not a directory, defaulting to '.'\n", dirname.c_str());
  m_Dirname = ".";
  return RESULT_FALSE;
}
Exemplo n.º 15
0
ASDCP::Result_t
ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len)
{
  m_KeyStart = m_ValueStart = 0;
  m_KLLength = m_ValueLength = 0;

  if ( memcmp(buf, SMPTE_UL_START, 4) != 0 )
    {
      DefaultLogSink().Error("Unexpected UL preamble: %02x.%02x.%02x.%02x\n",
			     buf[0], buf[1], buf[2], buf[3]);
      return RESULT_FAIL;
    }

  ui32_t ber_len = Kumu::BER_length(buf + SMPTE_UL_LENGTH);

  if ( ber_len > ( buf_len - SMPTE_UL_LENGTH ) )
    {
      DefaultLogSink().Error("BER encoding length exceeds buffer size\n");
      return RESULT_FAIL;
    }

  if ( ber_len == 0 )
    {
      DefaultLogSink().Error("KLV format error, zero BER length not allowed\n");
      return RESULT_FAIL;
    }

  ui64_t tmp_size;
  if ( ! Kumu::read_BER(buf + SMPTE_UL_LENGTH, &tmp_size) )
       return RESULT_FAIL;

  assert (tmp_size <= 0xFFFFFFFFL);
  m_ValueLength = (ui32_t) tmp_size;
  m_KLLength = SMPTE_UL_LENGTH + Kumu::BER_length(buf + SMPTE_UL_LENGTH);
  m_KeyStart = buf;
  m_ValueStart = buf + m_KLLength;
  return RESULT_OK;
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
0
Result_t
ASDCP::TimedText::LocalFilenameResolver::ResolveRID(const byte_t* uuid, TimedText::FrameBuffer& FrameBuf) const
{
  Result_t result = RESULT_NOT_FOUND;
  char buf[64];
  UUID RID(uuid);
  PathList_t found_list;

  FindInPath(PathMatchRegex(RID.EncodeHex(buf, 64)), m_Dirname, found_list);

  if ( found_list.size() == 1 )
    {
      FileReader Reader;
      DefaultLogSink().Debug("retrieving resource %s from file %s\n", buf, found_list.front().c_str());

      result = Reader.OpenRead(found_list.front().c_str());

      if ( KM_SUCCESS(result) )
	{
	  ui32_t read_count, read_size = Reader.Size();
	  result = FrameBuf.Capacity(read_size);
      
	  if ( KM_SUCCESS(result) )
	    result = Reader.Read(FrameBuf.Data(), read_size, &read_count);

	  if ( KM_SUCCESS(result) )
	    FrameBuf.Size(read_count);
	}
    }
  else if ( ! found_list.empty() )
    {
      DefaultLogSink().Error("More than one file in %s matches %s.\n", m_Dirname.c_str(), buf);
      result = RESULT_RAW_FORMAT;
    }

  return result;
}
Exemplo n.º 18
0
  inline Result_t Goto_EXT()
  {
    switch ( m_State )
      {
	case ST_PIC:
	case ST_EXT:
	case ST_SEQ:
	case ST_GOP:
	  m_State = ST_EXT;
	  return RESULT_OK;
      }

    DefaultLogSink().Error("EXT follows %s\n", StringParserState(m_State));
    return RESULT_STATE;
  }
Exemplo n.º 19
0
  inline Result_t Goto_GOP()
  {
    switch ( m_State )
      {
      case ST_EXT:
      case ST_SEQ:
	m_State = ST_GOP;
	return RESULT_OK;
      default:
	break;
      }
    
    DefaultLogSink().Error("GOP follows %s\n", StringParserState(m_State));
    return RESULT_STATE;
  }
Exemplo n.º 20
0
ASDCP::Result_t
ASDCP::RF64::SimpleRF64Header::ReadFromFile(const Kumu::FileReader& InFile, ui32_t* data_start)
{
  ui32_t read_count = 0;
  ui32_t local_data_start = 0;
  ASDCP::PCM::FrameBuffer TmpBuffer(Wav::MaxWavHeader);

  if ( data_start == 0 )
    data_start = &local_data_start;

  Result_t result = InFile.Read(TmpBuffer.Data(), TmpBuffer.Capacity(), &read_count);

  if ( ASDCP_SUCCESS(result) )
    result = ReadFromBuffer(TmpBuffer.RoData(), read_count, data_start);
  else
    DefaultLogSink().Error("Failed to read %d bytes from file\n", Wav::MaxWavHeader);

    return result;
}
Exemplo n.º 21
0
ASDCP::Result_t
ASDCP::KLVPacket::WriteKLToBuffer(ASDCP::FrameBuffer& Buffer, const UL& label, ui32_t length)
{
  assert(label.HasValue());

  if ( Buffer.Size() + kl_length > Buffer.Capacity() )
    {
      DefaultLogSink().Error("Small write buffer\n");
      return RESULT_FAIL;
    }
  
  memcpy(Buffer.Data() + Buffer.Size(), label.Value(), label.Size());

  if ( ! Kumu::write_BER(Buffer.Data() + Buffer.Size() + SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
    return RESULT_FAIL;

  Buffer.Size(Buffer.Size() + kl_length);
  return RESULT_OK;
}
Exemplo n.º 22
0
ASDCP::MXF::TLVReader::TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
  MemIOReader(p, c), m_Lookup(PrimerLookup)
{
  Result_t result = RESULT_OK;

  while ( Remainder() > 0 && ASDCP_SUCCESS(result) )
    {
      TagValue Tag;
      ui16_t pkt_len = 0;

      if ( MemIOReader::ReadUi8(&Tag.a) )
	if ( MemIOReader::ReadUi8(&Tag.b) )
	  if ( MemIOReader::ReadUi16BE(&pkt_len) )
	    {
	      m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
	      if ( SkipOffset(pkt_len) )
		continue;;
	    }

      DefaultLogSink().Error("Malformed Set\n");
      m_ElementMap.clear();
      result = RESULT_KLV_CODING(__LINE__, __FILE__);
    }
}
Exemplo n.º 23
0
ASDCP::Result_t
ASDCP::MPEG2::Parser::h__Parser::ReadFrame(FrameBuffer& FB)
{
  Result_t result = RESULT_OK;
  ui32_t write_offset = 0;
  ui32_t read_count = 0;

  FB.Size(0);

  if ( m_EOF )
    return RESULT_ENDOFFILE;

  // Data is read in VESReadSize chunks. Each chunk is parsed, and the
  // process is stopped when a Sequence or Picture header is found or when
  // the input file is exhausted. The partial next frame is cached for the
  // next call.
  m_ParserDelegate.Reset();
  m_Parser.Reset();

  if ( m_TmpBuffer.Size() > 0 )
    {
      memcpy(FB.Data(), m_TmpBuffer.RoData(), m_TmpBuffer.Size());
      result = m_Parser.Parse(FB.RoData(), m_TmpBuffer.Size());
      write_offset = m_TmpBuffer.Size();
      m_TmpBuffer.Size(0);
    }

  while ( ! m_ParserDelegate.m_CompletePicture && result == RESULT_OK )
    {
      if ( FB.Capacity() < ( write_offset + VESReadSize ) )
	{
	  DefaultLogSink().Error("FrameBuf.Capacity: %u FrameLength: %u\n",
				 FB.Capacity(), ( write_offset + VESReadSize ));
	  return RESULT_SMALLBUF;
	}

      result = m_FileReader.Read(FB.Data() + write_offset, VESReadSize, &read_count);

      if ( result == RESULT_ENDOFFILE || read_count == 0 )
	{
	  m_EOF = true;

	  if ( write_offset > 0 )
	    result = RESULT_OK;
	}

      if ( ASDCP_SUCCESS(result) )
	{
	  result = m_Parser.Parse(FB.RoData() + write_offset, read_count);
	  write_offset += read_count;
	}

      if ( m_EOF )
	break;
    }
  assert(m_ParserDelegate.m_FrameSize <= write_offset);

  if ( ASDCP_SUCCESS(result)
       && m_ParserDelegate.m_FrameSize < write_offset )
    {
      assert(m_TmpBuffer.Size() == 0);
      ui32_t diff = write_offset - m_ParserDelegate.m_FrameSize;
      assert(diff <= m_TmpBuffer.Capacity());

      memcpy(m_TmpBuffer.Data(), FB.RoData() + m_ParserDelegate.m_FrameSize, diff);
      m_TmpBuffer.Size(diff);
    }

  if ( ASDCP_SUCCESS(result) )
    {
      const byte_t* p = FB.RoData();
      if ( p[0] != 0 || p[1] != 0 || p[2] != 1 || ! ( p[3] == SEQ_START || p[3] == PIC_START ) )
        {
          DefaultLogSink().Error("Frame buffer does not begin with a PIC or SEQ start code.\n");
          return RESULT_RAW_FORMAT;
        }
    }

  if ( ASDCP_SUCCESS(result) )
    {
      FB.Size(m_ParserDelegate.m_FrameSize);
      FB.TemporalOffset(m_ParserDelegate.m_TemporalRef);
      FB.FrameType(m_ParserDelegate.m_FrameType);
      FB.PlaintextOffset(m_ParserDelegate.m_PlaintextOffset);
      FB.FrameNumber(m_FrameNumber++);
      FB.GOPStart(m_ParserDelegate.m_HasGOP);
      FB.ClosedGOP(m_ParserDelegate.m_ClosedGOP);
    }

  return result;
}
Exemplo n.º 24
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;
}
Exemplo n.º 25
0
ASDCP::Result_t
ASDCP::RF64::SimpleRF64Header::WriteToFile(Kumu::FileWriter& OutFile) const
{
  static ui32_t fmt_len =
    sizeof(format)
    + sizeof(nchannels)
    + sizeof(samplespersec)
    + sizeof(avgbps)
    + sizeof(blockalign)
    + sizeof(bitspersample)
    + sizeof(cbsize);

  ui32_t write_count = 0;
  ui64_t RIFF_len = data_len + SimpleWavHeaderLength - 8;
  //  DefaultLogSink().Debug("RIFF_len is %llu.\n", RIFF_len);
  byte_t* tmp_header = NULL;
  ui32_t header_len = 0;

  if (RIFF_len > MAX_RIFF_LEN)
  {
    DefaultLogSink().Debug("Will write out an RF64 wave file.\n");
    ui32_t data32_len = ((data_len < MAX_RIFF_LEN) ? data_len : MAX_RIFF_LEN);
    ui64_t data64_len = ((data_len < MAX_RIFF_LEN) ? 0 : data_len);
    static ui32_t ds64_len =
            sizeof(RIFF_len)
            + sizeof(data64_len)
            + sizeof(SAMPLE_COUNT)
            + sizeof(TABLE_LEN);

    header_len = SIMPLE_RF64_HEADER_LEN;
    tmp_header = new byte_t[header_len];
    byte_t* p = tmp_header;
    memcpy(p, &FCC_RF64, sizeof(fourcc)); p += 4;
    *((ui32_t*)p) = KM_i32_LE(MAX_RIFF_LEN); p += 4;
    memcpy(p, &Wav::FCC_WAVE, sizeof(fourcc)); p += 4;
    memcpy(p, &FCC_ds64, sizeof(fourcc)); p += 4;
    *((ui32_t*)p) = KM_i32_LE(ds64_len); p += 4;
    *((ui64_t*)p) = KM_i64_LE(RIFF_len); p += 8;
    *((ui64_t*)p) = KM_i64_LE(data64_len); p += 8;
    *((ui64_t*)p) = KM_i64_LE(SAMPLE_COUNT); p += 8;
    *((ui32_t*)p) = KM_i32_LE(TABLE_LEN); p += 4;
    memcpy(p, &Wav::FCC_fmt_, sizeof(fourcc)); p += 4;
    *((ui32_t*)p) = KM_i32_LE(fmt_len); p += 4;
    *((ui16_t*)p) = KM_i16_LE(format); p += 2;
    *((ui16_t*)p) = KM_i16_LE(nchannels); p += 2;
    *((ui32_t*)p) = KM_i32_LE(samplespersec); p += 4;
    *((ui32_t*)p) = KM_i32_LE(avgbps); p += 4;
    *((ui16_t*)p) = KM_i16_LE(blockalign); p += 2;
    *((ui16_t*)p) = KM_i16_LE(bitspersample); p += 2;
    *((ui16_t*)p) = KM_i16_LE(cbsize); p += 2;
    memcpy(p, &Wav::FCC_data, sizeof(fourcc)); p += 4;
    *((ui32_t*)p) = KM_i32_LE(data32_len); p += 4;
    write_count = (p - tmp_header);
  }
  else
  {
    DefaultLogSink().Debug("Will write out a regular wave file.\n");
    header_len = SimpleWavHeaderLength;
    tmp_header = new byte_t[header_len];
    byte_t* p = tmp_header;
    memcpy(p, &Wav::FCC_RIFF, sizeof(fourcc)); p += 4;
    *((ui32_t*)p) = KM_i32_LE(RIFF_len); p += 4;
    memcpy(p, &Wav::FCC_WAVE, sizeof(fourcc)); p += 4;
    memcpy(p, &Wav::FCC_fmt_, sizeof(fourcc)); p += 4;
    *((ui32_t*)p) = KM_i32_LE(fmt_len); p += 4;
    *((ui16_t*)p) = KM_i16_LE(format); p += 2;
    *((ui16_t*)p) = KM_i16_LE(nchannels); p += 2;
    *((ui32_t*)p) = KM_i32_LE(samplespersec); p += 4;
    *((ui32_t*)p) = KM_i32_LE(avgbps); p += 4;
    *((ui16_t*)p) = KM_i16_LE(blockalign); p += 2;
    *((ui16_t*)p) = KM_i16_LE(bitspersample); p += 2;
    *((ui16_t*)p) = KM_i16_LE(cbsize); p += 2;
    memcpy(p, &Wav::FCC_data, sizeof(fourcc)); p += 4;
    *((ui32_t*)p) = KM_i32_LE(data_len); p += 4;
    write_count = (p - tmp_header);
  }
  if (header_len != write_count)
  {
      DefaultLogSink().Warn("Expected to write %u bytes but wrote %u bytes for header.\n",
                            header_len, write_count);
  }
  write_count = 0;
  ASDCP::Result_t r = OutFile.Write(tmp_header, header_len, &write_count);
  delete [] tmp_header;
  return r;
}
Exemplo n.º 26
0
ASDCP::Result_t
ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len, ui32_t* data_start)
{
  if ( buf_len < SimpleWavHeaderLength )
    return RESULT_SMALLBUF;

  *data_start = 0;
  const byte_t* p = buf;
  const byte_t* end_p = p + buf_len;

  fourcc test_RIFF(p); p += 4;
  if ( test_RIFF != FCC_RIFF )
    {
      //      DefaultLogSink().Debug("File does not begin with RIFF header\n");      
      return RESULT_RAW_FORMAT;
    }

  ui32_t RIFF_len = KM_i32_LE(*(ui32_t*)p); p += 4;

  fourcc test_WAVE(p); p += 4;
  if ( test_WAVE != FCC_WAVE )
    {
      DefaultLogSink().Debug("File does not contain a WAVE header\n");
      return RESULT_RAW_FORMAT;
    }

  fourcc test_fcc;

  while ( p < end_p )
    {
      test_fcc = fourcc(p); p += 4;
      ui32_t chunk_size = KM_i32_LE(*(ui32_t*)p); p += 4;

      if ( test_fcc == FCC_data )
	{
	  if ( chunk_size > RIFF_len )
	    {
	      DefaultLogSink().Error("Chunk size %u larger than file: %u\n", chunk_size, RIFF_len);
	      return RESULT_RAW_FORMAT;
	    }

	  data_len = chunk_size;
	  *data_start = p - buf;
	  break;
	}

      if ( test_fcc == FCC_fmt_ )
	{
	  ui16_t format = KM_i16_LE(*(ui16_t*)p); p += 2;

	  if ( format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_EXTENSIBLE )
	    {
	      DefaultLogSink().Error("Expecting uncompressed PCM data, got format type %hd\n", format);
	      return RESULT_RAW_FORMAT;
	    }

	  nchannels = KM_i16_LE(*(ui16_t*)p); p += 2;
	  samplespersec = KM_i32_LE(*(ui32_t*)p); p += 4;
	  avgbps = KM_i32_LE(*(ui32_t*)p); p += 4;
	  blockalign = KM_i16_LE(*(ui16_t*)p); p += 2;
	  bitspersample = KM_i16_LE(*(ui16_t*)p); p += 2;
	  p += chunk_size - 16; // 16 is the number of bytes read in this block
	}
      else
	{
	  p += chunk_size;
	}
    }

  if ( *data_start == 0 ) // can't have no data!
    {
      DefaultLogSink().Error("No data chunk found, file contains no essence\n");
      return RESULT_RAW_FORMAT;
    }

  return RESULT_OK;
}
Exemplo n.º 27
0
ASDCP::Result_t
ASDCP::AIFF::SimpleAIFFHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len, ui32_t* data_start)
{
  if ( buf_len < 32 )
    return RESULT_SMALLBUF;

  *data_start = 0;
  const byte_t* p = buf;
  const byte_t* end_p = p + buf_len;

  fourcc test_FORM(p); p += 4;
  if ( test_FORM != FCC_FORM )
    {
      //      DefaultLogSink().Debug("File does not begin with FORM header\n");
      return RESULT_RAW_FORMAT;
    }

  ui32_t RIFF_len = KM_i32_BE(*(ui32_t*)p); p += 4;

  fourcc test_AIFF(p); p += 4;
  if ( test_AIFF != FCC_AIFF )
    {
      DefaultLogSink().Debug("File does not contain an AIFF header\n");
      return RESULT_RAW_FORMAT;
    }

  fourcc test_fcc;

  while ( p < end_p )
    {
      test_fcc = fourcc(p); p += 4;
      ui32_t chunk_size = KM_i32_BE(*(ui32_t*)p); p += 4;

      if ( test_fcc == FCC_COMM )
	{
	  numChannels = KM_i16_BE(*(ui16_t*)p); p += 2;
	  numSampleFrames = KM_i32_BE(*(ui32_t*)p); p += 4;
	  sampleSize = KM_i16_BE(*(ui16_t*)p); p += 2;
	  memcpy(sampleRate, p, 10);
	  p += 10;
	}
      else if ( test_fcc == FCC_SSND )
	{
	  if ( chunk_size > RIFF_len )
            {
              DefaultLogSink().Error("Chunk size %u larger than file: %u\n", chunk_size, RIFF_len);
              return RESULT_RAW_FORMAT;
            }

	  ui32_t offset = KM_i32_BE(*(ui32_t*)p); p += 4;
	  p += 4; // blockSize;

	  data_len = chunk_size - 8;
	  *data_start = (p - buf) + offset;
	  break;
	}
      else
	{
	  p += chunk_size;
	}
    }

  if ( *data_start == 0 ) // can't have no data!
    {
      DefaultLogSink().Error("No data chunk found, file contains no essence\n");
      return RESULT_RAW_FORMAT;
    }

  return RESULT_OK;
}
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;
}
Exemplo n.º 29
0
Result_t
ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::OpenRead()
{
  if ( ! m_Root.ParseString(m_XMLDoc.c_str()) )
    return RESULT_FORMAT;

  m_TDesc.EncodingName = "UTF-8"; // the XML parser demands UTF-8
  m_TDesc.ResourceList.clear();
  m_TDesc.ContainerDuration = 0;
  const XMLNamespace* ns = m_Root.Namespace();

  if ( ns == 0 )
    {
      DefaultLogSink(). Warn("Document has no namespace name, assuming %s\n", c_dcst_namespace_name);
      m_TDesc.NamespaceName = c_dcst_namespace_name;
    }
  else
    {
      m_TDesc.NamespaceName = ns->Name();
    }

  UUID DocID;
  if ( ! get_UUID_from_child_element("Id", &m_Root, DocID) )
    {
      DefaultLogSink(). Error("Id element missing from input document\n");
      return RESULT_FORMAT;
    }

  memcpy(m_TDesc.AssetID, DocID.Value(), DocID.Size());
  XMLElement* EditRate = m_Root.GetChildWithName("EditRate");

  if ( EditRate == 0 )
    {
      DefaultLogSink(). Error("EditRate element missing from input document\n");
      return RESULT_FORMAT;
    }

  m_TDesc.EditRate = decode_rational(EditRate->GetBody().c_str());

  if ( m_TDesc.EditRate != EditRate_23_98
       && m_TDesc.EditRate != EditRate_24
       && m_TDesc.EditRate != EditRate_25
       && m_TDesc.EditRate != EditRate_30
       && m_TDesc.EditRate != EditRate_48
       && m_TDesc.EditRate != EditRate_50
       && m_TDesc.EditRate != EditRate_60 )
    {
      DefaultLogSink(). Error("Unexpected EditRate: %d/%d\n",
			      m_TDesc.EditRate.Numerator, m_TDesc.EditRate.Denominator);
      return RESULT_FORMAT;
    }

  // list of fonts
  ElementList FontList;
  m_Root.GetChildrenWithName("LoadFont", FontList);

  for ( Elem_i i = FontList.begin(); i != FontList.end(); i++ )
    {
      UUID AssetID;
      if ( ! get_UUID_from_element(*i, AssetID) )
	{
	  DefaultLogSink(). Error("LoadFont element does not contain a urn:uuid value as expected.\n");
	  return RESULT_FORMAT;
	}

      TimedTextResourceDescriptor TmpResource;
      memcpy(TmpResource.ResourceID, AssetID.Value(), UUIDlen);
      TmpResource.Type = MT_OPENTYPE;
      m_TDesc.ResourceList.push_back(TmpResource);
      m_ResourceTypes.insert(ResourceTypeMap_t::value_type(UUID(TmpResource.ResourceID), MT_OPENTYPE));
    }

  // list of images
  ElementList ImageList;
  m_Root.GetChildrenWithName("Image", ImageList);
  std::set<Kumu::UUID> visited_items;

  for ( Elem_i i = ImageList.begin(); i != ImageList.end(); i++ )
    {
      UUID AssetID;
      if ( ! get_UUID_from_element(*i, AssetID) )
	{
	  DefaultLogSink(). Error("Image element does not contain a urn:uuid value as expected.\n");
	  return RESULT_FORMAT;
	}

      if ( visited_items.find(AssetID) == visited_items.end() )
	{
	  TimedTextResourceDescriptor TmpResource;
	  memcpy(TmpResource.ResourceID, AssetID.Value(), UUIDlen);
	  TmpResource.Type = MT_PNG;
	  m_TDesc.ResourceList.push_back(TmpResource);
	  m_ResourceTypes.insert(ResourceTypeMap_t::value_type(UUID(TmpResource.ResourceID), MT_PNG));
	  visited_items.insert(AssetID);
	}
    }

  // Calculate the timeline duration.
  // This is a little ugly because the last element in the file is not necessarily
  // the last instance to be displayed, e.g., element n and element n-1 may have the
  // same start time but n-1 may have a greater duration making it the last to be seen.
  // We must scan the list to accumulate the latest TimeOut value.
  ElementList InstanceList;
  ElementList::const_iterator ei;
  ui32_t end_count = 0;
  
  m_Root.GetChildrenWithName("Subtitle", InstanceList);

  if ( InstanceList.empty() )
    {
      DefaultLogSink(). Error("XML document contains no Subtitle elements.\n");
      return RESULT_FORMAT;
    }

  // assumes edit rate is constrained above
  ui32_t TCFrameRate = ( m_TDesc.EditRate == EditRate_23_98  ) ? 24 : m_TDesc.EditRate.Numerator;

  S12MTimecode beginTC;
  beginTC.SetFPS(TCFrameRate);
  XMLElement* StartTime = m_Root.GetChildWithName("StartTime");

  if ( StartTime != 0 )
    beginTC.DecodeString(StartTime->GetBody());

  for ( ei = InstanceList.begin(); ei != InstanceList.end(); ei++ )
    {
      S12MTimecode tmpTC((*ei)->GetAttrWithName("TimeOut"), TCFrameRate);
      if ( end_count < tmpTC.GetFrames() )
	end_count = tmpTC.GetFrames();
    }

  if ( end_count <= beginTC.GetFrames() )
    {
      DefaultLogSink(). Error("Timed Text file has zero-length timeline.\n");
      return RESULT_FORMAT;
    }

  m_TDesc.ContainerDuration = end_count - beginTC.GetFrames();

  return RESULT_OK;
}
Exemplo n.º 30
0
// TODO: refactor to use InitFromBuffer
ASDCP::Result_t
ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader)
{
  ui32_t read_count;
  byte_t tmp_data[tmp_read_size];
  ui64_t tmp_size;
  m_KeyStart = m_ValueStart = 0;
  m_KLLength = m_ValueLength = 0;
  m_Buffer.Size(0);

  Result_t result = Reader.Read(tmp_data, tmp_read_size, &read_count);

  if ( ASDCP_FAILURE(result) )
    return result;

  if ( read_count < (SMPTE_UL_LENGTH + 1) )
    {
      DefaultLogSink().Error("Short read of Key and Length got %u\n", read_count);
      return RESULT_READFAIL;
    }

  if ( memcmp(tmp_data, SMPTE_UL_START, 4) != 0 )
    {
      DefaultLogSink().Error("Unexpected UL preamble: %02x.%02x.%02x.%02x\n",
			     tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);
      return RESULT_FAIL;
    }

  if ( ! Kumu::read_BER(tmp_data + SMPTE_UL_LENGTH, &tmp_size) )
    {
      DefaultLogSink().Error("BER Length decoding error\n");
      return RESULT_FAIL;
    }

  if ( tmp_size > MAX_KLV_PACKET_LENGTH )
    {
      Kumu::ui64Printer tmp_size_str(tmp_size);
      DefaultLogSink().Error("Packet length %s exceeds internal limit\n", tmp_size_str.c_str());
      return RESULT_FAIL;
    }

  ui32_t remainder = 0;
  ui32_t ber_len = Kumu::BER_length(tmp_data + SMPTE_UL_LENGTH);
  m_KLLength = SMPTE_UL_LENGTH + ber_len;
  assert(tmp_size <= 0xFFFFFFFFL);
  m_ValueLength = (ui32_t) tmp_size;
  ui32_t packet_length = m_ValueLength + m_KLLength;

  result = m_Buffer.Capacity(packet_length);

  if ( ASDCP_FAILURE(result) )
    return result;

  m_KeyStart = m_Buffer.Data();
  m_ValueStart = m_Buffer.Data() + m_KLLength;
  m_Buffer.Size(packet_length);

  // is the whole packet in the tmp buf?
  if ( packet_length <= tmp_read_size )
    {
      assert(packet_length <= read_count);
      memcpy(m_Buffer.Data(), tmp_data, packet_length);

      if ( (remainder = read_count - packet_length) != 0 )
	{
	  DefaultLogSink().Warn("Repositioning pointer for short packet\n");
	  Kumu::fpos_t pos = Reader.Tell();
	  assert(pos > remainder);
	  result = Reader.Seek(pos - remainder);
	}
    }
  else
    {
      if ( read_count < tmp_read_size )
	{
	  DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
				 m_Buffer.Size(), read_count);
	  return RESULT_READFAIL;
	}

      memcpy(m_Buffer.Data(), tmp_data, tmp_read_size);
      remainder = m_Buffer.Size() - tmp_read_size;

      if ( remainder > 0 )
	{
	  result = Reader.Read(m_Buffer.Data() + tmp_read_size, remainder, &read_count);
      
	  if ( read_count != remainder )
	    {
	      DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
				     remainder+tmp_read_size, read_count+tmp_read_size);
	      result = RESULT_READFAIL;
	    }
	}
    }

  return result;
}