Skip to content

Commit

Permalink
Merge pull request #1358 from CastagnaIT/fix_sidx
Browse files Browse the repository at this point in the history
[AdaptiveStream] Fix sidx/init parsing
  • Loading branch information
CastagnaIT authored Aug 21, 2023
2 parents 59c3274 + 31e5e7c commit 6b10ca4
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 184 deletions.
144 changes: 75 additions & 69 deletions src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,7 @@ void CSession::UpdateStream(CStream& stream)
stream.m_info.SetCodecInternalName(codecStr);
}

AP4_Movie* CSession::PrepareStream(CStream* stream, bool& needRefetch)
void CSession::PrepareStream(CStream* stream, bool& needRefetch)
{
needRefetch = false;
CRepresentation* repr = stream->m_adStream.getRepresentation();
Expand All @@ -1022,10 +1022,10 @@ AP4_Movie* CSession::PrepareStream(CStream* stream, bool& needRefetch)
stream->m_adStream.getAdaptationSet(), repr))
{
case PrepareRepStatus::FAILURE:
return nullptr;
return;
case PrepareRepStatus::DRMCHANGED:
if (!InitializeDRM())
return nullptr;
return;
[[fallthrough]];
case PrepareRepStatus::DRMUNCHANGED:
stream->m_isEncrypted = repr->m_psshSetPos != PSSHSET_POS_DEFAULT;
Expand All @@ -1034,72 +1034,6 @@ AP4_Movie* CSession::PrepareStream(CStream* stream, bool& needRefetch)
default:
break;
}

if (repr->GetContainerType() == ContainerType::MP4 && !repr->HasInitPrefixed() &&
!repr->HasInitSegment())
{
//We'll create a Movie out of the things we got from manifest file
//note: movie will be deleted in destructor of stream->input_file_
AP4_Movie* movie{new AP4_Movie()};

AP4_SyntheticSampleTable* sample_table{new AP4_SyntheticSampleTable()};

AP4_SampleDescription* sample_descryption;
const std::string& extradata = repr->GetCodecPrivateData();

if (stream->m_info.GetCodecName() == "h264")
{
AP4_MemoryByteStream ms{reinterpret_cast<const uint8_t*>(extradata.data()),
static_cast<const AP4_Size>(extradata.size())};
AP4_AvccAtom* atom{AP4_AvccAtom::Create(AP4_ATOM_HEADER_SIZE + extradata.size(), ms)};
sample_descryption =
new AP4_AvcSampleDescription(AP4_SAMPLE_FORMAT_AVC1, stream->m_info.GetWidth(),
stream->m_info.GetHeight(), 0, nullptr, atom);
}
else if (stream->m_info.GetCodecName() == "hevc")
{
AP4_MemoryByteStream ms{reinterpret_cast<const AP4_UI08*>(extradata.data()),
static_cast<const AP4_Size>(extradata.size())};
AP4_HvccAtom* atom{AP4_HvccAtom::Create(AP4_ATOM_HEADER_SIZE + extradata.size(), ms)};
sample_descryption =
new AP4_HevcSampleDescription(AP4_SAMPLE_FORMAT_HEV1, stream->m_info.GetWidth(),
stream->m_info.GetHeight(), 0, nullptr, atom);
}
else if (stream->m_info.GetCodecName() == "av1")
{
AP4_MemoryByteStream ms{reinterpret_cast<const AP4_UI08*>(extradata.data()),
static_cast<AP4_Size>(extradata.size())};
AP4_Av1cAtom* atom = AP4_Av1cAtom::Create(AP4_ATOM_HEADER_SIZE + extradata.size(), ms);
sample_descryption =
new AP4_Av1SampleDescription(AP4_SAMPLE_FORMAT_AV01, stream->m_info.GetWidth(),
stream->m_info.GetHeight(), 0, nullptr, atom);
}
else if (stream->m_info.GetCodecName() == "srt")
sample_descryption = new AP4_SampleDescription(AP4_SampleDescription::TYPE_SUBTITLES,
AP4_SAMPLE_FORMAT_STPP, 0);
else
sample_descryption = new AP4_SampleDescription(AP4_SampleDescription::TYPE_UNKNOWN, 0, 0);

if (repr->GetPsshSetPos() != PSSHSET_POS_DEFAULT)
{
AP4_ContainerAtom schi{AP4_ATOM_TYPE_SCHI};
schi.AddChild(
new AP4_TencAtom(AP4_CENC_CIPHER_AES_128_CTR, 8,
GetDefaultKeyId(repr->GetPsshSetPos())));
sample_descryption = new AP4_ProtectedSampleDescription(
0, sample_descryption, 0, AP4_PROTECTION_SCHEME_TYPE_PIFF, 0, "", &schi);
}
sample_table->AddSampleDescription(sample_descryption);
movie->AddTrack(new AP4_Track(static_cast<AP4_Track::Type>(stream->m_adStream.GetTrackType()),
sample_table, CFragmentedSampleReader::TRACKID_UNKNOWN,
repr->GetTimescale(), 0, repr->GetTimescale(), 0, "", 0, 0));
//Create a dumy MOOV Atom to tell Bento4 its a fragmented stream
AP4_MoovAtom* moov{new AP4_MoovAtom()};
moov->AddChild(new AP4_ContainerAtom(AP4_ATOM_TYPE_MVEX));
movie->SetMoovAtom(moov);
return movie;
}
return nullptr;
}

void CSession::EnableStream(CStream* stream, bool enable)
Expand Down Expand Up @@ -1628,3 +1562,75 @@ bool CSession::SeekChapter(int ch)
}
return false;
}

AP4_Movie* CSession::CreateMovieAtom(CStream* stream)
{
CRepresentation* repr = stream->m_adStream.getRepresentation();

if (repr->GetContainerType() == ContainerType::MP4 && !repr->HasInitSegment())
{
AP4_SampleDescription* sampleDesc;
const std::string& extradata = repr->GetCodecPrivateData();

if (stream->m_info.GetCodecName() == CODEC::NAME_H264)
{
AP4_MemoryByteStream ms{reinterpret_cast<const uint8_t*>(extradata.data()),
static_cast<const AP4_Size>(extradata.size())};
AP4_AvccAtom* atom{AP4_AvccAtom::Create(AP4_ATOM_HEADER_SIZE + extradata.size(), ms)};
sampleDesc = new AP4_AvcSampleDescription(AP4_SAMPLE_FORMAT_AVC1, stream->m_info.GetWidth(),
stream->m_info.GetHeight(), 0, nullptr, atom);
}
else if (stream->m_info.GetCodecName() == CODEC::NAME_HEVC)
{
AP4_MemoryByteStream ms{reinterpret_cast<const AP4_UI08*>(extradata.data()),
static_cast<const AP4_Size>(extradata.size())};
AP4_HvccAtom* atom{AP4_HvccAtom::Create(AP4_ATOM_HEADER_SIZE + extradata.size(), ms)};
sampleDesc = new AP4_HevcSampleDescription(AP4_SAMPLE_FORMAT_HEV1, stream->m_info.GetWidth(),
stream->m_info.GetHeight(), 0, nullptr, atom);
}
else if (stream->m_info.GetCodecName() == CODEC::NAME_AV1)
{
AP4_MemoryByteStream ms{reinterpret_cast<const AP4_UI08*>(extradata.data()),
static_cast<AP4_Size>(extradata.size())};
AP4_Av1cAtom* atom = AP4_Av1cAtom::Create(AP4_ATOM_HEADER_SIZE + extradata.size(), ms);
sampleDesc = new AP4_Av1SampleDescription(AP4_SAMPLE_FORMAT_AV01, stream->m_info.GetWidth(),
stream->m_info.GetHeight(), 0, nullptr, atom);
}
else if (stream->m_info.GetCodecName() == CODEC::NAME_SRT)
{
sampleDesc = new AP4_SampleDescription(AP4_SampleDescription::TYPE_SUBTITLES,
AP4_SAMPLE_FORMAT_STPP, 0);
}
else
{
LOG::LogF(LOGWARNING,
"Created sample desciption atom of unknown type, codec \"%s\" is not handled",
stream->m_info.GetCodecName().c_str());
sampleDesc = new AP4_SampleDescription(AP4_SampleDescription::TYPE_UNKNOWN, 0, 0);
}

if (repr->GetPsshSetPos() != PSSHSET_POS_DEFAULT)
{
AP4_ContainerAtom schi{AP4_ATOM_TYPE_SCHI};
schi.AddChild(
new AP4_TencAtom(AP4_CENC_CIPHER_AES_128_CTR, 8, GetDefaultKeyId(repr->GetPsshSetPos())));
sampleDesc = new AP4_ProtectedSampleDescription(
0, sampleDesc, 0, AP4_PROTECTION_SCHEME_TYPE_PIFF, 0, "", &schi);
}

AP4_SyntheticSampleTable* sampleTable{new AP4_SyntheticSampleTable()};
sampleTable->AddSampleDescription(sampleDesc);

// Note: AP4_Movie ptr will be deleted from AP4_File destructor of CStream
AP4_Movie* movie{new AP4_Movie()};
movie->AddTrack(new AP4_Track(static_cast<AP4_Track::Type>(stream->m_adStream.GetTrackType()),
sampleTable, CFragmentedSampleReader::TRACKID_UNKNOWN,
repr->GetTimescale(), 0, repr->GetTimescale(), 0, "", 0, 0));
// Create MOOV Atom to allow bento4 to handle stream as fragmented MP4
AP4_MoovAtom* moov{new AP4_MoovAtom()};
moov->AddChild(new AP4_ContainerAtom(AP4_ATOM_TYPE_MVEX));
movie->SetMoovAtom(moov);
return movie;
}
return nullptr;
}
11 changes: 8 additions & 3 deletions src/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,8 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver
/*! \brief Update stream's InputstreamInfo
* \param stream The stream to prepare
* \param needRefetch [OUT] Set to true if stream info has changed
* \return The Movie box if the stream container is MP4 and a valid MOOV
* box is found, otherwise nullptr
*/
AP4_Movie* PrepareStream(CStream* stream, bool& needRefetch);
void PrepareStream(CStream* stream, bool& needRefetch);


/*! \brief Get a stream by index (starting at 1)
Expand Down Expand Up @@ -333,6 +331,13 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver
*/
void OnStreamChange(adaptive::AdaptiveStream* adStream) override;

/*!
* \brief Create a Movie (MOOV) atom from scratch based on manifest info.
* \param stream The stream where to get the info
* \return The Movie atom if success, otherwise nullptr
*/
AP4_Movie* CreateMovieAtom(CStream* stream);

protected:
/*!
* \brief Event raised when the current segment is changed and
Expand Down
Loading

0 comments on commit 6b10ca4

Please sign in to comment.