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;}
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; }
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; }
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; }
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)); }
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; }
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; }
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()); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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__); } }
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; }
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; }
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; }
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; }
// 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; }
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; }