Auto-update width/height/fps for livestreamed H264 and VP8 tracks, regardless of input type
This commit is contained in:
parent
3cc258834c
commit
cbe4f017f3
2 changed files with 51 additions and 0 deletions
50
src/io.cpp
50
src/io.cpp
|
@ -7,6 +7,7 @@
|
|||
#include <mist/json.h>
|
||||
#include <mist/langcodes.h> //LTS
|
||||
#include <mist/stream.h>
|
||||
#include <mist/h264.h>
|
||||
|
||||
namespace Mist{
|
||||
InOutBase::InOutBase() : M(meta){}
|
||||
|
@ -356,6 +357,7 @@ namespace Mist{
|
|||
// Determine if we need to open the next page
|
||||
uint32_t nextPageNum = INVALID_KEY_NUM;
|
||||
if (isKeyframe){
|
||||
updateTrackFromKeyframe(packTrack, packData, packDataSize);
|
||||
uint64_t endPage = tPages.getEndPos();
|
||||
|
||||
// If there is no page, create it
|
||||
|
@ -418,4 +420,52 @@ namespace Mist{
|
|||
bufferNext(packTime, packOffset, packTrack, packData, packDataSize, packBytePos, isKeyframe);
|
||||
}
|
||||
|
||||
///Handles updating track metadata from a new keyframe, if applicable
|
||||
void InOutBase::updateTrackFromKeyframe(uint32_t packTrack, const char *packData, size_t packDataSize){
|
||||
if (meta.getCodec(packTrack) == "H264"){
|
||||
//H264 packets are 4-byte size-prepended NAL units
|
||||
size_t offset = 0;
|
||||
while (offset+4 < packDataSize){
|
||||
uint32_t nalLen = Bit::btohl(packData+offset);
|
||||
if (nalLen+offset+4 > packDataSize){
|
||||
FAIL_MSG("Corrupt H264 keyframe packet: NAL unit of size %" PRIu32 " at position %zu exceeds packet size of %zu", nalLen, offset, packDataSize);
|
||||
return;
|
||||
}
|
||||
uint8_t nalType = (packData[offset+4] & 0x1F);
|
||||
if (nalType == 7){//SPS, update width/height/FPS
|
||||
h264::SPSMeta hMeta = h264::sequenceParameterSet(packData+offset+4, nalLen).getCharacteristics();
|
||||
meta.setWidth(packTrack, hMeta.width);
|
||||
meta.setHeight(packTrack, hMeta.height);
|
||||
meta.setFpks(packTrack, hMeta.fps*1000);
|
||||
}
|
||||
offset += nalLen+4;
|
||||
}
|
||||
}
|
||||
if (meta.getCodec(packTrack) == "VP8"){
|
||||
//VP8 packets have a simple header for keyframes
|
||||
//Reference: https://www.rfc-editor.org/rfc/rfc6386.html#section-9.1
|
||||
if (packData[3] == 0x9d && packData[4] == 0x01 && packData[5] == 0x2a){
|
||||
//Probably a valid key frame
|
||||
uint16_t pixWidth = Bit::btohs_le(packData+6);
|
||||
uint16_t pixHeight = Bit::btohs_le(packData+8);
|
||||
uint32_t w = pixWidth & 0x3fff;
|
||||
uint32_t h = pixHeight & 0x3fff;
|
||||
switch (pixWidth >> 14){
|
||||
case 1: w *= 5/4; break;
|
||||
case 2: w *= 5/3; break;
|
||||
case 3: w *= 2; break;
|
||||
}
|
||||
switch (pixHeight >> 14){
|
||||
case 1: h *= 5/4; break;
|
||||
case 2: h *= 5/3; break;
|
||||
case 3: h *= 2; break;
|
||||
}
|
||||
meta.setWidth(packTrack, w);
|
||||
meta.setHeight(packTrack, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}// namespace Mist
|
||||
|
|
1
src/io.h
1
src/io.h
|
@ -30,6 +30,7 @@ namespace Mist{
|
|||
size_t packDataSize, uint64_t packBytePos, bool isKeyframe);
|
||||
|
||||
protected:
|
||||
void updateTrackFromKeyframe(uint32_t packTrack, const char *packData, size_t packDataSize);
|
||||
bool standAlone;
|
||||
|
||||
DTSC::Packet thisPacket; // The current packet that is being parsed
|
||||
|
|
Loading…
Add table
Reference in a new issue