/*---------------------------------------------------------------------- | AP4_FileByteStream::AP4_FileByteStream +---------------------------------------------------------------------*/ AP4_FileByteStream::AP4_FileByteStream(const char* name, AP4_FileByteStream::Mode mode) { AP4_ByteStream* stream = NULL; AP4_Result result = AP4_KodiFileByteStream::Create(this, name, mode, stream); if (AP4_FAILED(result)) throw AP4_Exception(result); m_Delegate = stream; }
/*---------------------------------------------------------------------- | AP4_DecryptingSampleReader::ReadSampleData +---------------------------------------------------------------------*/ AP4_Result AP4_DecryptingSampleReader::ReadSampleData(AP4_Sample& sample, AP4_DataBuffer& sample_data) { AP4_Result result = sample.ReadData(m_DataBuffer); if (AP4_FAILED(result)) return result; return m_Decrypter->DecryptSampleData(m_DataBuffer, sample_data); }
/*---------------------------------------------------------------------- | AP4_OdafAtom::Create +---------------------------------------------------------------------*/ AP4_OdafAtom* AP4_OdafAtom::Create(AP4_Size size, AP4_ByteStream& stream) { AP4_UI08 version; AP4_UI32 flags; if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL; if (version != 0) return NULL; return new AP4_OdafAtom(size, version, flags, stream); }
/*---------------------------------------------------------------------- | AP4_TfhdAtom::Create +---------------------------------------------------------------------*/ AP4_TfhdAtom* AP4_TfhdAtom::Create(AP4_Size size, AP4_ByteStream& stream) { AP4_UI32 version; AP4_UI32 flags; if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL; if (version > 0) return NULL; if (size != ComputeSize(flags)) return NULL; return new AP4_TfhdAtom(size, version, flags, stream); }
/*---------------------------------------------------------------------- | AP4_BlocAtom::Create +---------------------------------------------------------------------*/ AP4_BlocAtom* AP4_BlocAtom::Create(AP4_Size size, AP4_ByteStream& stream) { AP4_UI08 version; AP4_UI32 flags; if (size < AP4_FULL_ATOM_HEADER_SIZE) return NULL; if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL; if (version > 1) return NULL; return new AP4_BlocAtom(size, version, flags, stream); }
/*---------------------------------------------------------------------- | AP4_PiffTrackEncryptionAtom::Create +---------------------------------------------------------------------*/ AP4_PiffTrackEncryptionAtom* AP4_PiffTrackEncryptionAtom::Create(AP4_Size size, AP4_ByteStream& stream) { AP4_UI08 version = 0; AP4_UI32 flags = 0; AP4_Result result = ReadFullHeader(stream, version, flags); if (AP4_FAILED(result)) return NULL; if (version != 0) return NULL; return new AP4_PiffTrackEncryptionAtom(size, version, flags, stream); }
/*---------------------------------------------------------------------- | AP4_RtpAtom::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_RtpAtom::WriteFields(AP4_ByteStream& stream) { AP4_Result result; // description format result = stream.WriteUI32(m_DescriptionFormat); if (AP4_FAILED(result)) return result; // sdp text result = stream.Write(m_SdpText.c_str(), m_SdpText.length()); if (AP4_FAILED(result)) return result; // pad with zeros if necessary AP4_Size padding = m_Size-(AP4_ATOM_HEADER_SIZE+4+m_SdpText.length()); while (padding--) stream.WriteUI08(0); return AP4_SUCCESS; }
/*---------------------------------------------------------------------- | AP4_IsmaTrackEncrypter::ProcessSample +---------------------------------------------------------------------*/ AP4_Result AP4_IsmaTrackEncrypter::ProcessSample(AP4_DataBuffer& data_in, AP4_DataBuffer& data_out) { AP4_Result result = m_Cipher->EncryptSample(data_in, data_out, m_ByteOffset, false); if (AP4_FAILED(result)) return result; m_ByteOffset += data_in.GetDataSize(); return AP4_SUCCESS; }
/*---------------------------------------------------------------------- | AP4_OddaAtom::SetEncryptedPayload +---------------------------------------------------------------------*/ AP4_Result AP4_OddaAtom::SetEncryptedPayload(AP4_ByteStream& stream) { // the new encrypted data length is the size of the stream AP4_LargeSize length; AP4_Result result = stream.GetSize(length); if (AP4_FAILED(result)) return result; return SetEncryptedPayload(stream, length); }
/*---------------------------------------------------------------------- | AP4_UnknownSampleEntry::ReadFields +---------------------------------------------------------------------*/ AP4_Result AP4_UnknownSampleEntry::ReadFields(AP4_ByteStream& stream) { // sample entry AP4_Result result = AP4_SampleEntry::ReadFields(stream); if (AP4_FAILED(result)) return result; // read the payload return stream.Read(m_Payload.UseData(), m_Payload.GetDataSize()); }
AP4_Track* AP4_Movie_GetTrackByIndex(AP4_Movie* self, AP4_Ordinal index) { AP4_Track* track = NULL; if (AP4_FAILED(self->GetTracks().Get(index, track))) { return NULL; } else { return track; } }
/*---------------------------------------------------------------------- | AP4_IsfmAtom::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_IsfmAtom::WriteFields(AP4_ByteStream& stream) { AP4_Result result; // selective encryption result = stream.WriteUI08(m_SelectiveEncryption ? 1 : 0); if (AP4_FAILED(result)) return result; // key indicator length result = stream.WriteUI08(m_KeyIndicatorLength); if (AP4_FAILED(result)) return result; // IV length result = stream.WriteUI08(m_IvLength); if (AP4_FAILED(result)) return result; return AP4_SUCCESS; }
/*---------------------------------------------------------------------- | AP4_Expandable::Write +---------------------------------------------------------------------*/ AP4_Result AP4_Expandable::Write(AP4_ByteStream& stream) { AP4_Result result; // write the class id switch (m_ClassIdSize) { case CLASS_ID_SIZE_08: result = stream.WriteUI08((AP4_UI08)m_ClassId); if (AP4_FAILED(result)) return result; break; default: return AP4_ERROR_INTERNAL; } // write the size AP4_ASSERT(m_HeaderSize-1 <= 8); AP4_ASSERT(m_HeaderSize >= 2); unsigned int size = m_PayloadSize; unsigned char bytes[8]; // last bytes of the encoded size bytes[m_HeaderSize-2] = size&0x7F; // leading bytes of the encoded size for (int i=m_HeaderSize-3; i>=0; i--) { // move to the next 7 bits size >>= 7; // output a byte with a top bit marker bytes[i] = (size&0x7F) | 0x80; } result = stream.Write(bytes, m_HeaderSize-1); if (AP4_FAILED(result)) return result; // write the fields WriteFields(stream); return result; }
/*---------------------------------------------------------------------- | AP4_StsdAtom::Create +---------------------------------------------------------------------*/ AP4_StsdAtom* AP4_StsdAtom::Create(AP4_Size size, AP4_ByteStream& stream, AP4_AtomFactory& atom_factory) { AP4_UI08 version; AP4_UI32 flags; if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL; if (version > 1) return NULL; return new AP4_StsdAtom(size, version, flags, stream, atom_factory); }
/*---------------------------------------------------------------------- | AP4_AtomFactory::CreateAtomFromStream +---------------------------------------------------------------------*/ AP4_Result AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream, AP4_Atom*& atom) { AP4_Size bytes_available = 0; if (AP4_FAILED(stream.GetSize(bytes_available)) || bytes_available == 0) { bytes_available = (AP4_Size)((unsigned long)(-1)); } return CreateAtomFromStream(stream, bytes_available, atom, NULL); }
/*---------------------------------------------------------------------- | AP4::Initialize +---------------------------------------------------------------------*/ AP4_Result AP4::Initialize() { AP4_Result result = AP4_SUCCESS; #if defined(AP4_CONFIG_CONSTRUCT_STATICS_ON_INITIALIZE) if (!AP4_DefaultAtomFactory::Instance.m_Initialized) { result = AP4_DefaultAtomFactory::Instance.Initialize(); if (AP4_FAILED(result)) return result; } if (!AP4_DefaultBlockCipherFactory::Instance.m_Initialized) { result = AP4_DefaultBlockCipherFactory::Instance.Initialize(); if (AP4_FAILED(result)) return result; } if (!AP4_MetaData::Initialized()) { AP4_MetaData::Initialize(); } #endif return result; }
/*---------------------------------------------------------------------- | IsIFrame +---------------------------------------------------------------------*/ static bool IsIFrame(AP4_Sample& sample, AP4_AvcSampleDescription* avc_desc) { AP4_DataBuffer sample_data; if (AP4_FAILED(sample.ReadData(sample_data))) { return false; } const unsigned char* data = sample_data.GetData(); AP4_Size size = sample_data.GetDataSize(); while (size >= avc_desc->GetNaluLengthSize()) { unsigned int nalu_length = 0; if (avc_desc->GetNaluLengthSize() == 1) { nalu_length = *data++; --size; } else if (avc_desc->GetNaluLengthSize() == 2) { nalu_length = AP4_BytesToUInt16BE(data); data += 2; size -= 2; } else if (avc_desc->GetNaluLengthSize() == 4) { nalu_length = AP4_BytesToUInt32BE(data); data += 4; size -= 4; } else { return false; } if (nalu_length <= size) { size -= nalu_length; } else { size = 0; } switch (*data & 0x1F) { case 1: { AP4_BitStream bits; bits.WriteBytes(data+1, 8); ReadGolomb(bits); unsigned int slice_type = ReadGolomb(bits); if (slice_type == 2 || slice_type == 7) { return true; } else { return false; // only show first slice type } } case 5: return true; } data += nalu_length; } return false; }
/*---------------------------------------------------------------------- | AP4_SampleRtpConstructor::DoWrite +---------------------------------------------------------------------*/ AP4_Result AP4_SampleRtpConstructor::DoWrite(AP4_ByteStream& stream) { AP4_Result result = stream.WriteUI08(m_TrackRefIndex); if (AP4_FAILED(result)) return result; result = stream.WriteUI16(m_Length); if (AP4_FAILED(result)) return result; result = stream.WriteUI32(m_SampleNum); if (AP4_FAILED(result)) return result; result = stream.WriteUI32(m_SampleOffset); if (AP4_FAILED(result)) return result; result = stream.WriteUI16(1); // bytes per block if (AP4_FAILED(result)) return result; return stream.WriteUI16(1); // samples per block }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int argc, char** argv) { AP4_Result result = AP4_SUCCESS; // parse the command line if (argc != 2) PrintUsageAndExit(); // create the input stream AP4_ByteStream* input; try { input = new AP4_FileByteStream(argv[1], AP4_FileByteStream::STREAM_MODE_READ); } catch (AP4_Exception) { fprintf(stderr, "ERROR: cannot open input file (%s)\n", argv[1]); return 1; } AP4_File* file = new AP4_File(*input); AP4_Movie* movie = file->GetMovie(); if (movie != NULL) { // get a hint track reader AP4_Track* hint_track = movie->GetTrack(AP4_Track::TYPE_HINT, 1); if (hint_track == NULL) { AP4_Debug("No hint track in this movie\n"); return AP4_FAILURE; } AP4_HintTrackReader reader(*hint_track, *movie, 0x01020304); AP4_String rtp_file_name(argv[1]); rtp_file_name += ".rtp"; // display the sdp AP4_String sdp; reader.GetSdpText(sdp); AP4_Debug("sdp:\n%s\n\n", sdp.c_str()); // dump the packet result = DumpRtpPackets(reader, rtp_file_name.c_str()); if (AP4_FAILED(result)) goto bail; } else { AP4_Debug("No movie found in the file\n"); return AP4_FAILURE; } bail: delete file; input->Release(); return result; }
/*---------------------------------------------------------------------- | AP4_DrefAtom::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_DrefAtom::WriteFields(AP4_ByteStream& stream) { AP4_Result result; // write the number of entries result = stream.WriteUI32(m_Children.ItemCount()); if (AP4_FAILED(result)) return result; // write the children return m_Children.Apply(AP4_AtomListWriter(stream)); }
/*---------------------------------------------------------------------- | AP4_StscAtom::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_StscAtom::WriteFields(AP4_ByteStream& stream) { AP4_Result result; // entry count AP4_Cardinal entry_count = m_Entries.ItemCount(); result = stream.WriteUI32(entry_count); // entries for (AP4_Ordinal i=0; i<entry_count; i++) { stream.WriteUI32(m_Entries[i].m_FirstChunk); if (AP4_FAILED(result)) return result; stream.WriteUI32(m_Entries[i].m_SamplesPerChunk); if (AP4_FAILED(result)) return result; stream.WriteUI32(m_Entries[i].m_SampleDescriptionIndex); if (AP4_FAILED(result)) return result; } return result; }
/*---------------------------------------------------------------------- | AP4_UnknownSampleEntry::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_UnknownSampleEntry::WriteFields(AP4_ByteStream& stream) { AP4_Result result; // write the fields of the base class result = AP4_SampleEntry::WriteFields(stream); if (AP4_FAILED(result)) return result; // write the payload return stream.Write(m_Payload.GetData(), m_Payload.GetDataSize()); }
/*---------------------------------------------------------------------- | AP4_StsdAtom::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_StsdAtom::WriteFields(AP4_ByteStream& stream) { AP4_Result result; // entry count result = stream.WriteUI32(m_Children.ItemCount()); if (AP4_FAILED(result)) return result; // entries return m_Children.Apply(AP4_AtomListWriter(stream)); }
/*---------------------------------------------------------------------- | AP4_OdheAtom::Create +---------------------------------------------------------------------*/ AP4_OdheAtom* AP4_OdheAtom::Create(AP4_Size size, AP4_ByteStream& stream, AP4_AtomFactory& atom_factory) { AP4_UI08 version; AP4_UI32 flags; if (size < AP4_FULL_ATOM_HEADER_SIZE) return NULL; if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL; if (version != 0) return NULL; return new AP4_OdheAtom(size, version, flags, stream, atom_factory); }
/*---------------------------------------------------------------------- | DecryptAndWriteSamples +---------------------------------------------------------------------*/ static void DecryptAndWriteSamples(AP4_Track* track, AP4_SampleDescription* sdesc, AP4_Byte* key, AP4_ByteStream* output) { AP4_ProtectedSampleDescription* pdesc = AP4_DYNAMIC_CAST(AP4_ProtectedSampleDescription, sdesc); if (pdesc == NULL) { fprintf(stderr, "ERROR: unable to obtain cipher info\n"); return; } // get the original sample description and make the prefix AP4_SampleDescription* orig_sdesc = pdesc->GetOriginalSampleDescription(); unsigned int nalu_length_size = 0; AP4_DataBuffer prefix; if (AP4_FAILED(MakeFramePrefix(orig_sdesc, prefix, nalu_length_size))) { return; } // create the decrypter AP4_SampleDecrypter* decrypter = AP4_SampleDecrypter::Create(pdesc, key, 16); if (decrypter == NULL) { fprintf(stderr, "ERROR: unable to create decrypter\n"); return; } AP4_Sample sample; AP4_DataBuffer encrypted_data; AP4_DataBuffer decrypted_data; AP4_Ordinal index = 0; while (AP4_SUCCEEDED(track->ReadSample(index, sample, encrypted_data))) { if (AP4_FAILED(decrypter->DecryptSampleData(encrypted_data, decrypted_data))) { fprintf(stderr, "ERROR: failed to decrypt sample\n"); return; } WriteSample(decrypted_data, prefix, nalu_length_size, output); index++; } }
/*---------------------------------------------------------------------- | AP4_TfhdAtom::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_TfhdAtom::WriteFields(AP4_ByteStream& stream) { AP4_Result result; result = stream.WriteUI32(m_TrackId); if (AP4_FAILED(result)) return result; if (m_Flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) { result = stream.WriteUI64(m_BaseDataOffset); if (AP4_FAILED(result)) return result; } if (m_Flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) { result = stream.WriteUI32(m_SampleDescriptionIndex); if (AP4_FAILED(result)) return result; } if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) { stream.WriteUI32(m_DefaultSampleDuration); if (AP4_FAILED(result)) return result; } if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) { stream.WriteUI32(m_DefaultSampleSize); if (AP4_FAILED(result)) return result; } if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) { stream.WriteUI32(m_DefaultSampleFlags); if (AP4_FAILED(result)) return result; } return AP4_SUCCESS; }
/*---------------------------------------------------------------------- | AP4_UuidAtom::WriteHeader +---------------------------------------------------------------------*/ AP4_Result AP4_UuidAtom::WriteHeader(AP4_ByteStream& stream) { AP4_Result result; // write the size result = stream.WriteUI32(m_Size32); if (AP4_FAILED(result)) return result; // write the type result = stream.WriteUI32(m_Type); if (AP4_FAILED(result)) return result; // handle 64-bit sizes if (m_Size32 == 1) { result = stream.WriteUI64(m_Size64); if (AP4_FAILED(result)) return result; } // write the extended type result = stream.Write(m_Uuid, 16); if (AP4_FAILED(result)) return result; // for full atoms, write version and flags if (m_IsFull) { result = stream.WriteUI08((AP4_UI08)m_Version); if (AP4_FAILED(result)) return result; result = stream.WriteUI24(m_Flags); if (AP4_FAILED(result)) return result; } return AP4_SUCCESS; }
/*---------------------------------------------------------------------- | AP4_TrefTypeAtom::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_TrefTypeAtom::WriteFields(AP4_ByteStream& stream) { AP4_Result result = AP4_SUCCESS; AP4_Size track_id_count = m_TrackIds.ItemCount(); for (AP4_Ordinal i=0; i<track_id_count; i++) { result = stream.WriteUI32(m_TrackIds[i]); if (AP4_FAILED(result)) return result; } return AP4_SUCCESS; }
virtual AP4_Result ProcessMoof(AP4_ContainerAtom* moof, AP4_Position moof_offset, AP4_Position mdat_payload_offset) { AP4_Result result; if (!~m_Track->GetId()) { AP4_TfhdAtom* tfhd = AP4_DYNAMIC_CAST(AP4_TfhdAtom, moof->FindChild("traf/tfhd")); m_Track->SetId(tfhd->GetTrackId()); } if (m_Observer) m_Observer->BeginFragment(m_StreamId); if (AP4_SUCCEEDED((result = AP4_LinearReader::ProcessMoof(moof, moof_offset, mdat_payload_offset))) && m_Protected_desc) { //Setup the decryption AP4_CencSampleInfoTable *sample_table; AP4_UI32 algorithm_id = 0; delete m_Decrypter; m_Decrypter = 0; AP4_ContainerAtom *traf = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moof->GetChild(AP4_ATOM_TYPE_TRAF, 0)); if (!m_Protected_desc || !traf) return AP4_ERROR_INVALID_FORMAT; if (AP4_FAILED(result = AP4_CencSampleInfoTable::Create(m_Protected_desc, traf, algorithm_id, *m_FragmentStream, moof_offset, sample_table))) return result; if (AP4_FAILED(result = AP4_CencSampleDecrypter::Create(sample_table, algorithm_id, 0, 0, 0, m_SingleSampleDecryptor, m_Decrypter))) return result; } if (m_Observer) m_Observer->EndFragment(m_StreamId); return result; }
/*---------------------------------------------------------------------- | AP4_IkmsAtom::WriteFields +---------------------------------------------------------------------*/ AP4_Result AP4_IkmsAtom::WriteFields(AP4_ByteStream& stream) { // kms uri AP4_Result result = stream.Write(m_KmsUri.c_str(), m_KmsUri.length()+1); if (AP4_FAILED(result)) return result; // pad with zeros if necessary AP4_Size padding = m_Size-(AP4_FULL_ATOM_HEADER_SIZE+m_KmsUri.length()+1); while (padding--) stream.WriteUI08(0); return AP4_SUCCESS; }