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/json.h>
|
||||||
#include <mist/langcodes.h> //LTS
|
#include <mist/langcodes.h> //LTS
|
||||||
#include <mist/stream.h>
|
#include <mist/stream.h>
|
||||||
|
#include <mist/h264.h>
|
||||||
|
|
||||||
namespace Mist{
|
namespace Mist{
|
||||||
InOutBase::InOutBase() : M(meta){}
|
InOutBase::InOutBase() : M(meta){}
|
||||||
|
@ -356,6 +357,7 @@ namespace Mist{
|
||||||
// Determine if we need to open the next page
|
// Determine if we need to open the next page
|
||||||
uint32_t nextPageNum = INVALID_KEY_NUM;
|
uint32_t nextPageNum = INVALID_KEY_NUM;
|
||||||
if (isKeyframe){
|
if (isKeyframe){
|
||||||
|
updateTrackFromKeyframe(packTrack, packData, packDataSize);
|
||||||
uint64_t endPage = tPages.getEndPos();
|
uint64_t endPage = tPages.getEndPos();
|
||||||
|
|
||||||
// If there is no page, create it
|
// If there is no page, create it
|
||||||
|
@ -418,4 +420,52 @@ namespace Mist{
|
||||||
bufferNext(packTime, packOffset, packTrack, packData, packDataSize, packBytePos, isKeyframe);
|
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
|
}// namespace Mist
|
||||||
|
|
1
src/io.h
1
src/io.h
|
@ -30,6 +30,7 @@ namespace Mist{
|
||||||
size_t packDataSize, uint64_t packBytePos, bool isKeyframe);
|
size_t packDataSize, uint64_t packBytePos, bool isKeyframe);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void updateTrackFromKeyframe(uint32_t packTrack, const char *packData, size_t packDataSize);
|
||||||
bool standAlone;
|
bool standAlone;
|
||||||
|
|
||||||
DTSC::Packet thisPacket; // The current packet that is being parsed
|
DTSC::Packet thisPacket; // The current packet that is being parsed
|
||||||
|
|
Loading…
Add table
Reference in a new issue