Support for AV1 MP4 input and output

This commit is contained in:
Thulinma 2023-06-11 16:26:27 +02:00
parent 8b8a28c4ec
commit a9abfa531e
12 changed files with 154 additions and 22 deletions

View file

@ -5,8 +5,9 @@
#include "defines.h"
#include "dtsc.h"
#include "encode.h"
#include "lib/shared_memory.h"
#include "lib/util.h"
#include "shared_memory.h"
#include "util.h"
#include "stream.h"
#include <arpa/inet.h> //for htonl/ntohl
#include <cstdlib>
#include <cstring>
@ -2710,6 +2711,7 @@ namespace DTSC{
std::string type = getType(*it);
trackJSON["codec"] = getCodec(*it);
trackJSON["codecstring"] = Util::codecString(getCodec(*it), getInit(*it));
trackJSON["type"] = type;
trackJSON["idx"] = (uint64_t)*it;
trackJSON["trackid"] = (uint64_t)getID(*it);

View file

@ -270,6 +270,8 @@ namespace MP4{
case 0x61616320: return ((AAC *)this)->toPrettyString(indent); break;
case 0x68766331:
case 0x68657631: return ((HEV1 *)this)->toPrettyString(indent); break;
case 0x61763031: return ((AV01 *)this)->toPrettyString(indent); break;
case 0x61763143: return ((AV1C *)this)->toPrettyString(indent); break;
case 0x61766331:
case 0x656E6376: // encv
return ((AVC1 *)this)->toPrettyString(indent);

View file

@ -799,6 +799,70 @@ namespace MP4{
return r.str();
}
AV1C::AV1C(){
memcpy(data + 4, "av1C", 4);
setInt8(0b10000001, 0); // Marker 1, version 1: 0b10000001
}
std::string AV1C::toPrettyString(uint32_t indent){
std::stringstream r;
r << std::string(indent, ' ') << "[av1C] AV1 Init Data (" << boxedSize() << ")" << std::endl;
r << std::string(indent + 1, ' ') << "Marker: " << (int)((getInt8(0) & 0b10000000) >> 7) << std::endl;
r << std::string(indent + 1, ' ') << "Version: " << (int)(getInt8(0) & 0b01111111) << std::endl;
r << std::string(indent + 1, ' ') << "Profile: " << (int)((getInt8(1) & 0b11100000) >> 5) << std::endl;
r << std::string(indent + 1, ' ') << "Level: " << (int)(getInt8(1) & 0b00011111) << std::endl;
r << std::string(indent + 1, ' ') << "Tier: " << (int)((getInt8(2) & 0b10000000) >> 7) << std::endl;
r << std::string(indent + 1, ' ') << "Bit depth: ";
switch ((getInt8(2) & 0b01100000)){
case 0b00000000: r << "8"; break;
case 0b01000000: r << "10"; break;
case 0b01100000: r << "12"; break;
case 0b00100000: r << "Unknown"; break;
}
r << std::endl;
r << std::string(indent + 1, ' ') << "Subsampling format: ";
switch ((getInt8(2) & 0b00011100)){
case 0b00000000: r << "YUV 4:4:4"; break;
case 0b00001000: r << "YUV 4:2:2"; break;
case 0b00001100: r << "YUV 4:2:0"; break;
case 0b00011100: r << "Monochrome 4:0:0"; break;
default: r << "Unknown";
}
r << std::endl;
r << std::string(indent + 1, ' ') << "Subsampling position: ";
switch ((getInt8(2) & 0b00000011)){
case 0: r << "Unknown"; break;
case 1: r << "Vertical"; break;
case 2: r << "Co-located"; break;
case 3: r << "Reserved"; break;
}
r << std::endl;
if (getInt8(3) & 0b00010000){
r << std::string(indent + 1, ' ') << "Initial presentation delay: " << (int)(getInt8(3) & 0b00001111) + 1 << std::endl;
}else{
r << std::string(indent + 1, ' ') << "Initial presentation delay: 0" << std::endl;
}
r << std::string(indent + 1, ' ') << (payloadSize() - 4) << "b of OBU initialization data" << std::endl;
return r.str();
}
void AV1C::setPayload(std::string newPayload){
if (!reserve(0, payloadSize(), newPayload.size())){
ERROR_MSG("Cannot allocate enough memory for payload");
return;
}
memcpy((char *)payload(), (char *)newPayload.c_str(), newPayload.size());
}
Descriptor::Descriptor(){
data = (char *)malloc(2);
data[0] = 0;
@ -2692,22 +2756,26 @@ namespace MP4{
avccBox.setPayload(M.getInit(idx));
setCLAP(avccBox);
}
/*LTS-START*/
if (tCodec == "HEVC"){
setCodec("hev1");
MP4::HVCC hvccBox;
hvccBox.setPayload(M.getInit(idx));
setCLAP(hvccBox);
}
/*LTS-END*/
if (tCodec == "AV1"){
setCodec("av01");
MP4::AV1C av1cBox;
av1cBox.setPayload(M.getInit(idx));
setCLAP(av1cBox);
}
MP4::PASP paspBox;
setPASP(paspBox);
}
void VisualSampleEntry::initialize(){
memcpy(data + 4, "erro", 4);
setHorizResolution(0x00480000);
setVertResolution(0x00480000);
setHorizResolution(72);
setVertResolution(72);
setFrameCount(1);
setCompressorName("");
setDepth(0x0018);
@ -2726,17 +2794,17 @@ namespace MP4{
uint16_t VisualSampleEntry::getHeight(){return getInt16(26);}
void VisualSampleEntry::setHorizResolution(uint32_t newHorizResolution){
setInt32(newHorizResolution, 28);
void VisualSampleEntry::setHorizResolution(double newHorizResolution){
setInt32(newHorizResolution * 65536.0, 28);
}
uint32_t VisualSampleEntry::getHorizResolution(){return getInt32(28);}
double VisualSampleEntry::getHorizResolution(){return getInt32(28) / 65536.0;}
void VisualSampleEntry::setVertResolution(uint32_t newVertResolution){
setInt32(newVertResolution, 32);
void VisualSampleEntry::setVertResolution(double newVertResolution){
setInt32(newVertResolution * 65536.0, 32);
}
uint32_t VisualSampleEntry::getVertResolution(){return getInt32(32);}
double VisualSampleEntry::getVertResolution(){return getInt32(32) / 65536.0;}
void VisualSampleEntry::setFrameCount(uint16_t newFrameCount){setInt16(newFrameCount, 40);}
@ -2839,8 +2907,8 @@ namespace MP4{
r << toPrettySampleString(indent);
r << std::string(indent + 1, ' ') << "Width: " << getWidth() << std::endl;
r << std::string(indent + 1, ' ') << "Height: " << getHeight() << std::endl;
r << std::string(indent + 1, ' ') << "HorizResolution: " << getHorizResolution() << std::endl;
r << std::string(indent + 1, ' ') << "VertResolution: " << getVertResolution() << std::endl;
r << std::string(indent + 1, ' ') << "HorizResolution: " << getHorizResolution() << " DPI" << std::endl;
r << std::string(indent + 1, ' ') << "VertResolution: " << getVertResolution() << " DPI" << std::endl;
r << std::string(indent + 1, ' ') << "FrameCount: " << getFrameCount() << std::endl;
r << std::string(indent + 1, ' ') << "CompressorName: " << getCompressorName() << std::endl;
r << std::string(indent + 1, ' ') << "Depth: " << getDepth() << std::endl;
@ -3249,6 +3317,12 @@ namespace MP4{
return toPrettyVisualString(indent, "[h264] H.264/MPEG-4 AVC");
}
AV01::AV01(){memcpy(data + 4, "av01", 4);}
std::string AV01::toPrettyString(uint32_t indent){
return toPrettyVisualString(indent, "[av01] AV1 Video");
}
FIEL::FIEL(){memcpy(data + 4, "fiel", 4);}
void FIEL::setTotal(char newTotal){setInt8(newTotal, 0);}

View file

@ -200,6 +200,13 @@ namespace MP4{
h265::metaInfo getMetaInfo();
};
class AV1C : public Box{
public:
AV1C();
void setPayload(std::string newPayload);
std::string toPrettyString(uint32_t indent = 0);
};
class Descriptor{
public:
Descriptor();
@ -694,10 +701,10 @@ namespace MP4{
uint16_t getWidth();
void setHeight(uint16_t newHeight);
uint16_t getHeight();
void setHorizResolution(uint32_t newHorizResolution);
uint32_t getHorizResolution();
void setVertResolution(uint32_t newVertResolution);
uint32_t getVertResolution();
void setHorizResolution(double newHorizResolution);
double getHorizResolution();
void setVertResolution(double newVertResolution);
double getVertResolution();
void setFrameCount(uint16_t newFrameCount);
uint16_t getFrameCount();
void setCompressorName(std::string newCompressorName);
@ -851,6 +858,12 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class AV01 : public VisualSampleEntry{
public:
AV01();
std::string toPrettyString(uint32_t indent = 0);
};
class FIEL : public Box{
public:
FIEL();

View file

@ -105,6 +105,26 @@ std::string Util::codecString(const std::string &codec, const std::string &initD
if (codec == "AAC"){return "mp4a.40.2";}
if (codec == "MP3"){return "mp4a.40.34";}
if (codec == "AC3"){return "mp4a.a5";}
if (codec == "AV1"){
if (initData.size() < 4){return "av01";}// Can't determine properties. :-(
std::stringstream r;
r << "av01.";
r << (int)((initData[1] & 0b11100000) >> 5); //profile
r << ".";
r << std::setw(2) << std::setfill('0') << (int)(initData[1] & 0b00011111); //level
r << ((initData[2] & 0b10000000)?"H":"M"); //tier
r << ".";
switch (initData[2] & 0b01100000){
case 0b00000000: r << "08"; break;
case 0b01000000: r << "10"; break;
case 0b01100000: r << "12"; break;
case 0b00100000: r << "??"; break;
}
/// \TODO Implement the full descriptor as in https://aomediacodec.github.io/av1-isobmff/#codecsparam
/// Init data follows this format:
/// https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-syntax
return r.str();
}
return "";
}