121 lines
4.9 KiB
C++
121 lines
4.9 KiB
C++
#include "analyser_ogg.h"
|
|
#include <mist/opus.h>
|
|
|
|
/// \TODO EW EW EW EW EW EW EW EW EW EW EW
|
|
|
|
void AnalyserOGG::init(Util::Config &conf){
|
|
Analyser::init(conf);
|
|
}
|
|
|
|
AnalyserOGG::AnalyserOGG(Util::Config &conf) : Analyser(conf){}
|
|
|
|
bool AnalyserOGG::parsePacket(){
|
|
if (!oggPage.read(stdin)){return false;}
|
|
|
|
// We now have an Ogg page
|
|
// Print it, if we're at high detail level.
|
|
DETAIL_HI("%s", oggPage.toPrettyString().c_str());
|
|
|
|
// attempt to detect codec if this is the first page of a stream
|
|
if (oggPage.getHeaderType() & OGG::BeginOfStream){
|
|
if (memcmp("theora", oggPage.getSegment(0) + 1, 6) == 0){
|
|
sn2Codec[oggPage.getBitstreamSerialNumber()] = "Theora";
|
|
}
|
|
if (memcmp("vorbis", oggPage.getSegment(0) + 1, 6) == 0){
|
|
sn2Codec[oggPage.getBitstreamSerialNumber()] = "Vorbis";
|
|
}
|
|
if (memcmp("OpusHead", oggPage.getSegment(0), 8) == 0){
|
|
sn2Codec[oggPage.getBitstreamSerialNumber()] = "Opus";
|
|
}
|
|
if (sn2Codec[oggPage.getBitstreamSerialNumber()] != ""){
|
|
INFO_MSG("Bitstream %llu recognized as %s", oggPage.getBitstreamSerialNumber(),
|
|
sn2Codec[oggPage.getBitstreamSerialNumber()].c_str());
|
|
}else{
|
|
WARN_MSG("Bitstream %llu not recognized!", oggPage.getBitstreamSerialNumber());
|
|
}
|
|
}
|
|
|
|
if (sn2Codec[oggPage.getBitstreamSerialNumber()] == "Theora"){
|
|
if (detail >= 2){
|
|
std::cout << " Theora data" << std::endl;
|
|
}
|
|
static unsigned int numParts = 0;
|
|
static unsigned int keyCount = 0;
|
|
for (unsigned int i = 0; i < oggPage.getAllSegments().size(); i++){
|
|
theora::header tmpHeader((char *)oggPage.getSegment(i), oggPage.getAllSegments()[i].size());
|
|
if (tmpHeader.isHeader()){
|
|
if (tmpHeader.getHeaderType() == 0){kfgshift = tmpHeader.getKFGShift();}
|
|
}else{
|
|
if (!(oggPage.getHeaderType() == OGG::Continued) &&
|
|
tmpHeader.getFTYPE() == 0){// if keyframe
|
|
if (detail >= 3){
|
|
std::cout << "keyframe " << keyCount << " has " << numParts << " parts and granule " << (oggPage.getGranulePosition() >> kfgshift) << std::endl;
|
|
}
|
|
numParts = 0;
|
|
keyCount++;
|
|
}
|
|
if (oggPage.getHeaderType() != OGG::Continued || i){numParts++;}
|
|
}
|
|
if (detail >= 2){
|
|
std::cout << tmpHeader.toPrettyString(4);
|
|
}
|
|
}
|
|
}else if (sn2Codec[oggPage.getBitstreamSerialNumber()] == "Vorbis"){
|
|
if (detail >= 2){
|
|
std::cout << " Vorbis data" << std::endl;
|
|
}
|
|
for (unsigned int i = 0; i < oggPage.getAllSegments().size(); i++){
|
|
int len = oggPage.getAllSegments()[i].size();
|
|
vorbis::header tmpHeader((char *)oggPage.getSegment(i), len);
|
|
if (tmpHeader.isHeader() && detail >= 2){std::cout << tmpHeader.toPrettyString(4);}
|
|
}
|
|
}else if (sn2Codec[oggPage.getBitstreamSerialNumber()] == "Opus"){
|
|
if (detail >= 2){
|
|
std::cout << " Opus data" << std::endl;
|
|
}
|
|
int offset = 0;
|
|
for (unsigned int i = 0; i < oggPage.getAllSegments().size(); i++){
|
|
int len = oggPage.getAllSegments()[i].size();
|
|
const char *part = oggPage.getSegment(i);
|
|
if (len >= 8 && memcmp(part, "Opus", 4) == 0){
|
|
if (memcmp(part, "OpusHead", 8) == 0 && detail >= 2){
|
|
std::cout << " Version: " << (int)(part[8]) << std::endl;
|
|
std::cout << " Channels: " << (int)(part[9]) << std::endl;
|
|
std::cout << " Pre-skip: " << (int)(part[10] + (part[11] << 8)) << std::endl;
|
|
std::cout << " Orig. sample rate: "
|
|
<< (int)(part[12] + (part[13] << 8) + (part[14] << 16) + (part[15] << 24))
|
|
<< std::endl;
|
|
std::cout << " Gain: " << (int)(part[16] + (part[17] << 8)) << std::endl;
|
|
std::cout << " Channel map: " << (int)(part[18]) << std::endl;
|
|
if (part[18] > 0){
|
|
std::cout << " Channel map family " << (int)(part[18])
|
|
<< " not implemented - output incomplete" << std::endl;
|
|
}
|
|
}
|
|
if (memcmp(part, "OpusTags", 8) == 0 && detail >= 3){
|
|
unsigned int vendor_len = part[8] + (part[9] << 8) + (part[10] << 16) + (part[11] << 24);
|
|
std::cout << " Vendor: " << std::string(part + 12, vendor_len) << std::endl;
|
|
const char *str_data = part + 12 + vendor_len;
|
|
unsigned int strings =
|
|
str_data[0] + (str_data[1] << 8) + (str_data[2] << 16) + (str_data[3] << 24);
|
|
std::cout << " Tags: (" << strings << ")" << std::endl;
|
|
str_data += 4;
|
|
for (unsigned int j = 0; j < strings; j++){
|
|
unsigned int strlen =
|
|
str_data[0] + (str_data[1] << 8) + (str_data[2] << 16) + (str_data[3] << 24);
|
|
str_data += 4;
|
|
std::cout << " [" << j << "] " << std::string((char *)str_data, strlen) << std::endl;
|
|
str_data += strlen;
|
|
}
|
|
}
|
|
}else{
|
|
if (detail >= 4){
|
|
std::cout << " " << Opus::Opus_prettyPacket(part, len) << std::endl;
|
|
}
|
|
}
|
|
offset += len;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|