parse FOURCCs found in MKV files

This commit is contained in:
Martchus 2015-06-11 00:27:34 +02:00
parent 43c33adedf
commit 5ceb7891e5
8 changed files with 538 additions and 36 deletions

View File

@ -78,28 +78,6 @@ AbstractTrack::AbstractTrack(iostream &stream, uint64 startOffset) :
AbstractTrack::~AbstractTrack()
{}
/*!
* \brief Returns the format of the track as C-style string if known; otherwise
* returns the format abbreviation or an empty string.
* \remarks
* - The caller must not free the returned string.
* - The string might get invalidated when the track is (re)parsed.
*/
const char *AbstractTrack::formatName() const
{
return m_format || m_formatName.empty() ? m_format.name() : m_formatName.c_str();
}
/*!
* \brief Returns the a more or less common abbreviation for the format of the track
* as C-style string if known; otherwise returns an empty string.
*/
const char *AbstractTrack::formatAbbreviation() const
{
const char *abbr = m_format.abbreviation();
return *abbr || m_formatId.empty() ? m_format.abbreviation() : m_formatId.c_str();
}
/*!
* \brief Returns the media type as string.
*/

View File

@ -54,6 +54,7 @@ public:
double version() const;
const char *formatName() const;
const char *formatAbbreviation() const;
const std::string &formatId() const;
MediaType mediaType() const;
const char *mediaTypeName() const;
uint64 size() const;
@ -239,6 +240,37 @@ inline double AbstractTrack::version() const
return m_version;
}
/*!
* \brief Returns the format of the track as C-style string if known; otherwise
* returns the format abbreviation or an empty string.
* \remarks
* - The caller must not free the returned string.
* - The string might get invalidated when the track is (re)parsed.
*/
inline const char *AbstractTrack::formatName() const
{
return m_format || m_formatName.empty() ? m_format.name() : m_formatName.c_str();
}
/*!
* \brief Returns the a more or less common abbreviation for the format of the track
* as C-style string if known; otherwise returns an empty string.
*/
inline const char *AbstractTrack::formatAbbreviation() const
{
const char *abbr = m_format.abbreviation();
return *abbr || m_formatId.empty() ? m_format.abbreviation() : m_formatId.c_str();
}
/*!
* \brief Returns the format ID (raw format identifier directly extracted from
* the container) if known; otherwise returns an empty string.
*/
inline const std::string &AbstractTrack::formatId() const
{
return m_formatId;
}
/*!
* \brief Returns the media type if known; otherwise returns MediaType::Other.
*/

51
avi/bitmapinfoheader.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "bitmapinfoheader.h"
#include <c++utilities/io/binaryreader.h>
using namespace IoUtilities;
namespace Media {
/*!
* \class Media::BitmapInfoHeader
* \brief The BitmapInfoHeader class parses the BITMAPINFOHEADER structure defined by MS.
*/
/*!
* \brief Constructs a new BitmapInfoHeader.
*/
BitmapInfoHeader::BitmapInfoHeader() :
size(0),
width(0),
height(0),
planes(0),
bitCount(0),
compression(0),
imageSize(0),
horizontalResolution(0),
verticalResolution(0),
clrUsed(0),
clrImportant(0)
{}
/*!
* \brief Parses the BITMAPINFOHEADER structure using the specified \a reader.
* \remarks 0x28 byte will be read from the associated stream.
*/
void BitmapInfoHeader::parse(BinaryReader &reader)
{
size = reader.readUInt32LE();
width = reader.readUInt32LE();
height = reader.readUInt32LE();
planes = reader.readUInt16LE();
bitCount = reader.readUInt16LE();
compression = reader.readUInt32BE();
imageSize = reader.readUInt32LE();
horizontalResolution = reader.readUInt32LE();
verticalResolution = reader.readUInt32LE();
clrUsed = reader.readUInt32LE();
clrImportant = reader.readUInt32LE();
}
} // namespace Media

35
avi/bitmapinfoheader.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef MEDIA_BITMAPINFOHEADER_H
#define MEDIA_BITMAPINFOHEADER_H
#include <c++utilities/application/global.h>
#include <c++utilities/conversion/types.h>
namespace IoUtilities {
class BinaryReader;
}
namespace Media {
class LIB_EXPORT BitmapInfoHeader
{
public:
BitmapInfoHeader();
void parse(IoUtilities::BinaryReader &reader);
uint32 size;
uint32 width;
uint32 height;
uint16 planes;
uint16 bitCount;
uint32 compression;
uint32 imageSize;
uint32 horizontalResolution;
uint32 verticalResolution;
uint32 clrUsed;
uint32 clrImportant;
};
} // namespace Media
#endif // MEDIA_BITMAPINFOHEADER_H

19
avi/mediafourcc.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "mediafourcc.h"
#include "../mediaformat.h"
namespace Media {
namespace Fourccs {
MediaFormat fourccToMediaFormat(uint32 fourcc) {
switch(fourcc) {
case XvidMpeg4:
return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg4Asp);
default: return MediaFormat(); // TODO: cover more FOURCCs
}
}
}
}

354
avi/mediafourcc.h Normal file
View File

@ -0,0 +1,354 @@
#ifndef MEDIAFOURCC_H
#define MEDIAFOURCC_H
#include <c++utilities/application/global.h>
#include <c++utilities/conversion/types.h>
namespace Media {
class MediaFormat;
namespace Fourccs {
enum KnownValues {
AMParedesPredictor = 0x31393738,
VuyBlackmagic = 0x32565559,
Ivx1 = 0x33495630,
Ivx2 = 0x33495631,
Ivx3 = 0x33495632,
FfmpegDivxMsMpeg4V3 = 0x33495644,
Ivx4 = 0x33495658,
PlanarRgbCodec = 0x38425053,
AutodeskAnimatorCodecRle1 = 0x41415334,
AutodeskAnimatorCodecRle2 = 0x41415343,
KensingtonCodec = 0x41425952,
StreamboxActl2 = 0x4143544C,
Wavecodec = 0x41445631,
Advj = 0x4144564A,
IntelIndeoVideo32 = 0x4145494B,
ArrayVideooneMpeg1ICapture = 0x41454D49,
AutodeskAnimatorFlc256Color = 0x41464C43,
AfliAutodeskAnimatorFli256Color = 0x41464C49,
Cineform10BitVisuallyPerfectHdWavelet = 0x41484456,
Ajpg = 0x414A5047,
Ampg = 0x414D5047,
Anim = 0x414E494D,
AngelpotionDefinitive1 = 0x41503431,
AngelpotionDefinitive2 = 0x41503432,
AlparysoftLosslessCodec = 0x41534C43,
AsusVideo = 0x41535631,
AsusVideo2 = 0x41535632,
AsusVideo20 = 0x41535658,
Atm4 = 0x41544D34,
Aura2CodecYuv422 = 0x41555232,
Aura1CodecYuv411 = 0x41555241,
Avc1 = 0x41564331,
Avrn = 0x4156524E,
Ba81 = 0x42413831,
BinkVideo = 0x42494E4B,
Blz0 = 0x424C5A30,
ProsumerVideo = 0x42543230,
Btcv = 0x42544356,
BroadwayMpegCapturecompression = 0x42573130,
Byr1 = 0x42595231,
Byr2 = 0x42595232,
Cc12 = 0x43433132,
Cdvc = 0x43445643,
Cfcc = 0x43464343,
Cgdi = 0x43474449,
Cham = 0x4348414D,
WebcamJpeg = 0x434A5047,
Cmyk = 0x434D594B,
Cpla = 0x43504C41,
Cram = 0x4352414D,
CamstudioCodec = 0x43534344,
Ctrx = 0x43545258,
Cinepak = 0x43564944,
Cwlt = 0x43574C54,
ConexantYuv411 = 0x43585931,
ConexantYuv422 = 0x43585932,
CreativeYuv = 0x43595556,
Cyuy = 0x43595559,
D261 = 0x44323631,
D263 = 0x44323633,
Davc = 0x44415643,
Dcl1 = 0x44434C31,
Dcl2 = 0x44434C32,
Dcl3 = 0x44434C33,
Dcl4 = 0x44434C34,
Dcl5 = 0x44434C35,
DivxMpeg41 = 0x44495633,
DivxMpeg42 = 0x44495634,
Div5 = 0x44495635,
Divx = 0x44495658,
Dm4V = 0x444D3456,
RainbowRunnerHardwareCompression = 0x444D4231,
Dmb2 = 0x444D4232,
Dmk2 = 0x444D4B32,
Dsvd = 0x44535644,
TruemotionS = 0x4455434B,
Dvcpro = 0x44563235,
Dvcpro50 = 0x44563530,
Dvan = 0x4456414E,
Dvcs = 0x44564353,
Dve2 = 0x44564532,
Smpte370M = 0x44564831,
ConsumerDv50Mbps = 0x44564844,
ConsumerDv25Mbps = 0x44565344,
ConsumerDv125Mbps = 0x4456534C,
Dvx1 = 0x44565831,
Dvx2 = 0x44565832,
Dvx3 = 0x44565833,
DivxMpeg43 = 0x44583530,
Dxgm = 0x4458474D,
Dxtc = 0x44585443,
Dxtn = 0x4458544E,
ElsaQuickCodec = 0x454B5130,
Elk0 = 0x454C4B30,
EtymonixMpeg2Video = 0x454D3256,
Eyestream7Codec = 0x45533037,
Escp = 0x45534350,
EtreppidVideoCodec1 = 0x45545631,
EtreppidVideoCodec2 = 0x45545632,
Etvc = 0x45545643,
FfmpegCodec = 0x46465631,
Fljp = 0x464C4A50,
Ffmpeg = 0x464D5034,
FmscreenCaptureCodec = 0x464D5643,
FrapsCodec = 0x46505331,
ForwardMotionJpegWithAlphaChannel = 0x46525741,
ForwardMotionJpeg = 0x46525744,
Fvf1 = 0x46564631,
Geompeg4 = 0x47454F58,
Gjpg = 0x474A5047,
MotionLzw = 0x474C5A57,
MotionJpeg1 = 0x47504547,
Gwlt = 0x47574C54,
H260ThroughH269 = 0x48323630,
RawYuv422 = 0x48445943,
H265Hevc = 0x48455643,
HuffmanLosslessCodec = 0x48465955,
Hmcr = 0x484D4352,
Hmrr = 0x484D5252,
ItuH263 = 0x49323633,
Iclb = 0x49434C42,
Igor = 0x49474F52,
Ijpg = 0x494A5047,
Ilvc = 0x494C5643,
Ilvr = 0x494C5652,
GigaAviDvCodec = 0x49504456,
Indeo21 = 0x49523231,
Iraw = 0x49524157,
Isme = 0x49534D45,
Indeo3 = 0x49563330,
Indeo32 = 0x49563332,
IndeoInteractive1 = 0x49563430,
IndeoInteractive2 = 0x49563530,
Jbyr = 0x4A425952,
JpegStillImage = 0x4A504547,
JpegLight = 0x4A50474C,
Kmvc = 0x4B4D5643,
L261 = 0x4C323631,
LeadH263 = 0x4C323633,
Lbyr = 0x4C425952,
LeadmcmwVideoCodec = 0x4C434D57,
LeadMjpeg20001 = 0x4C435732,
LeadVideoCodec = 0x4C454144,
Lgry = 0x4C475259,
LeadJpeg411 = 0x4C4A3131,
LeadJpeg422 = 0x4C4A3232,
LeadMjpeg20002 = 0x4C4A324B,
LeadJpeg444 = 0x4C4A3434,
LeadMjpegCodec = 0x4C4A5047,
LeadMpeg2VideoCodec = 0x4C4D5032,
LeadMpeg4VideoCodec = 0x4C4D5034,
Lsvc = 0x4C535643,
Lsvm = 0x4C53564D,
LightningStrikeVideoCodec = 0x4C535658,
LempelzivoberhumerCodec = 0x4C5A4F31,
M261 = 0x4D323631,
M263 = 0x4D323633,
M4CcM4Cc = 0x4D344343,
M4S2 = 0x4D345332,
Mc12 = 0x4D433132,
Mcam = 0x4D43414D,
MotionJpeg2000 = 0x4D4A3243,
MotionJpeg2 = 0x4D4A5047,
Mmes = 0x4D4D4553,
EvalDownload1 = 0x4D503241,
EvalDownload2 = 0x4D503254,
EvalDownload3 = 0x4D503256,
Mpeg4 = 0x4D503432,
Mp43 = 0x4D503433,
EvalDownload4 = 0x4D503441,
Mp4S = 0x4D503453,
EvalDownload5 = 0x4D503454,
EvalDownload6 = 0x4D503456,
Mpeg = 0x4D504547,
Mpg4 = 0x4D504734,
Mpgi = 0x4D504749,
Mr16 = 0x4D523136,
Mrca = 0x4D524341,
Mrle = 0x4D524C45,
Msvc = 0x4D535643,
Avimszh = 0x4D535A48,
Mtx1ThroughMtx9 = 0x4D545831,
MotionPixelsMvi1Codec = 0x4D564931,
MotionPixelsMvi2Codec = 0x4D564932,
AwareMotionWavelets = 0x4D575631,
Navi = 0x4E415649,
Ndsc = 0x4E445343,
Ndsm = 0x4E44534D,
Ndsp = 0x4E445350,
Ndss = 0x4E445353,
Ndxc = 0x4E445843,
Ndxh = 0x4E445848,
Ndxp = 0x4E445850,
Ndxs = 0x4E445853,
Nhvu = 0x4E485655,
Ntn1 = 0x4E544E31,
Ntn2 = 0x4E544E32,
Nvds = 0x4E564453,
Nvhs = 0x4E564853,
Nvs0Nvs5 = 0x4E565330,
Nvt0Nvt5 = 0x4E565430,
DvcCodec = 0x50445643,
Pgvv = 0x50475656,
Phmo = 0x50484D4F,
Pim1 = 0x50494D31,
Pim2 = 0x50494D32,
PegasusLosslessJpeg = 0x50494D4A,
VideoXl = 0x5049584C,
Pjpg = 0x504A5047,
Pvez = 0x5056455A,
Pvmm = 0x50564D4D,
PegasusWavelet2000Compression = 0x50565732,
Qpeg = 0x51504547,
Qpeq = 0x51504551,
Rgbt = 0x52474254,
Rle = 0x524C450,
Rle4 = 0x524C4534,
Rle8 = 0x524C4538,
Rmp4 = 0x524D5034,
AppleVideo = 0x52505A41,
Rt21 = 0x52543231,
Rv20 = 0x52563230,
Rv30 = 0x52563330,
Rv40 = 0x52563430,
VideocapC210 = 0x53343232,
San3 = 0x53414E33,
Sdcc = 0x53444343,
Sedg = 0x53454447,
SurfaceFittingMethod = 0x53464D43,
Smp4 = 0x534D5034,
Smsc = 0x534D5343,
Smsd = 0x534D5344,
Smsv = 0x534D5356,
Sp40 = 0x53503430,
Sp44 = 0x53503434,
Sp54 = 0x53503534,
Spig = 0x53504947,
Sqz2 = 0x53515A32,
Stva = 0x53545641,
Stvb = 0x53545642,
Stvc = 0x53545643,
Stvx = 0x53545658,
Stvy = 0x53545659,
VideoR1 = 0x53563130,
SorensonVideo1 = 0x53565131,
Svq3 = 0x53565133,
Tlms = 0x544C4D53,
Tlst = 0x544C5354,
Tm20 = 0x544D3230,
Tm2X = 0x544D3258,
Tmic = 0x544D4943,
Tmot = 0x544D4F54,
TruemotionRt20 = 0x54523230,
TechsmithScreenCaptureCodec = 0x54534343,
Tv10 = 0x54563130,
Tvjp = 0x54564A50,
Tvmj = 0x54564D4A,
Ty0N = 0x5459304E,
Ty2C = 0x54593243,
Ty2N = 0x5459324E,
Clearvideo = 0x55434F44,
Ultimotion = 0x554C5449,
V210 = 0x56323130,
V261 = 0x56323631,
V655 = 0x56363535,
Vcr1 = 0x56435231,
Vcr2 = 0x56435232,
Vcr39 = 0x56435233,
Vdct = 0x56444354,
Vdom = 0x56444F4D,
Vdow = 0x56444F57,
VideotizerYuvCodec = 0x5644545A,
Videogrampix = 0x56475058,
Vids = 0x56494453,
VfapiCodec = 0x56494650,
Vivo = 0x5649564F,
Vixl = 0x5649584C,
Vlv1 = 0x564C5631,
Vp30 = 0x56503330,
Vp31 = 0x56503331,
Vp40 = 0x56503430,
Vp50 = 0x56503530,
Vp60 = 0x56503630,
Vp61 = 0x56503631,
Vp62 = 0x56503632,
Vp70 = 0x56503730,
Vp80 = 0x56503830,
Vqc1 = 0x56514331,
Vqc2 = 0x56514332,
Vqjc = 0x56514A43,
VssVideo = 0x56535356,
Vuuu = 0x56555555,
Vx1K = 0x5658314B,
Vx2K = 0x5658324B,
Vxsp = 0x56585350,
AtiYuv1 = 0x56595539,
AtiYuv2 = 0x56595559,
Wbvc = 0x57425643,
Wham = 0x5748414D,
WinnovSoftwareCompression = 0x57494E58,
WinbondJpeg = 0x574A5047,
Wmv1 = 0x574D5631,
Wmv2 = 0x574D5632,
WindowsMediaVideo9 = 0x574D5633,
Wmva = 0x574D5641,
WinnovHardwareCompression = 0x574E5631,
Wvc1 = 0x57564331,
X263 = 0x58323633,
H264 = 0x58323634,
Xlv0 = 0x584C5630,
Xmpg = 0x584D5047,
XvidMpeg4 = 0x58564944,
Xwv0Xwv9 = 0x58575630,
Xxan = 0x5858414E,
BppGrayscaleVideo = 0x5931360,
Y411 = 0x59343131,
BrooktreeYuv411 = 0x59343150,
Y444 = 0x59343434,
Y8 = 0x593800,
Yc12 = 0x59433132,
Yuv8 = 0x59555638,
Yuv9RawFormat = 0x59555639,
Yuvp = 0x59555650,
Yuy2 = 0x59555932,
Yuyv = 0x59555956,
Yuv420Planar = 0x59563132,
Yv16 = 0x59563136,
Yv92 = 0x59563932,
Zlib = 0x5A4C4942,
TheDoxboxProject = 0x5A4D4256,
Zpeg = 0x5A504547,
Zygovideo = 0x5A59474F
};
LIB_EXPORT MediaFormat fourccToMediaFormat(uint32 fourcc);
}
}
#endif // MEDIAFOURCC_H

View File

@ -3,6 +3,9 @@
#include "matroskacontainer.h"
#include "matroskaid.h"
#include "../avi/bitmapinfoheader.h"
#include "../avi/mediafourcc.h"
#include "../mediaformat.h"
#include "../exceptions.h"
@ -60,7 +63,7 @@ MediaFormat MatroskaTrack::codecIdToMediaFormat(const string &codecId)
fmt.sub = SubFormats::Mpeg4Sp;
} else if(part3 == "ASP") {
fmt.sub = SubFormats::Mpeg4Asp;
} else if(part3 == "AP") {
} else if(part3 == "AVC") {
fmt.sub = SubFormats::Mpeg4Avc;
}
} else if(part2 == "MS" && part3 == "V3") {
@ -181,17 +184,15 @@ MediaFormat MatroskaTrack::codecIdToMediaFormat(const string &codecId)
void MatroskaTrack::internalParseHeader()
{
const string context("parsing header of Matroska track");
static const string context("parsing header of Matroska track");
try {
m_trackElement->parse();
} catch(Failure &) {
addNotification(NotificationType::Critical, "Unable to parse track element.", context);
throw;
}
EbmlElement *trackInfoElement = m_trackElement->firstChild(), *subElement = nullptr;
while(trackInfoElement) {
// read information about the track from the childs of the track entry element
for(EbmlElement *trackInfoElement = m_trackElement->firstChild(), *subElement = nullptr; trackInfoElement; trackInfoElement = trackInfoElement->nextSibling()) {
try {
trackInfoElement->parse();
} catch (Failure &) {
@ -258,7 +259,8 @@ void MatroskaTrack::internalParseHeader()
case MatroskaIds::ColorSpace:
m_colorSpace = subElement->readUInteger();
break;
default: ;
default:
;
}
subElement = subElement->nextSibling();
}
@ -282,7 +284,8 @@ void MatroskaTrack::internalParseHeader()
case MatroskaIds::SamplingFrequency:
m_sampleRate = subElement->readFloat();
break;
default: ;
default:
;
}
subElement = subElement->nextSibling();
}
@ -308,6 +311,8 @@ void MatroskaTrack::internalParseHeader()
case MatroskaIds::CodecName:
m_formatName = trackInfoElement->readString();
break;
case MatroskaIds::CodecDelay:
break; // TODO
case MatroskaIds::TrackFlagEnabled:
m_enabled = trackInfoElement->readUInteger();
break;
@ -323,7 +328,8 @@ void MatroskaTrack::internalParseHeader()
case MatroskaIds::DefaultDuration:
defaultDuration = trackInfoElement->readUInteger();
break;
default: ;
default:
;
}
switch(m_mediaType) {
case MediaType::Video:
@ -331,10 +337,33 @@ void MatroskaTrack::internalParseHeader()
m_fps = 1000000000.0 / static_cast<double>(defaultDuration);
}
break;
default: ;
default:
;
}
trackInfoElement = trackInfoElement->nextSibling();
}
// read further information from the CodecPrivate element for some codecs
switch(m_format.general) {
EbmlElement *codecPrivateElement;
case GeneralMediaFormat::MicrosoftVideoCodecManager:
case GeneralMediaFormat::MicrosoftAudioCodecManager:
if((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate))) {
// parse bitmap info header to determine actual format
if(codecPrivateElement->dataSize() >= 0x28) {
m_istream->seekg(codecPrivateElement->dataOffset());
BitmapInfoHeader bitmapInfoHeader;
bitmapInfoHeader.parse(reader());
m_formatId.reserve(m_formatId.size() + 7);
m_formatId += " \"";
m_formatId += interpretIntegerAsString(bitmapInfoHeader.compression);
m_formatId += "\"";
m_format += Fourccs::fourccToMediaFormat(bitmapInfoHeader.compression);
} else {
addNotification(NotificationType::Critical, "BITMAPINFOHEADER structure (in \"CodecPrivate\"-element) is truncated.", context);
}
}
break;
default:
;
}
}

View File

@ -68,7 +68,9 @@ SOURCES += \
matroska/matroskaattachment.cpp \
mediaformat.cpp \
avc/avcconfiguration.cpp \
mp4/mpeg4descriptor.cpp
mp4/mpeg4descriptor.cpp \
avi/mediafourcc.cpp \
avi/bitmapinfoheader.cpp
HEADERS += \
abstractcontainer.h \
@ -134,7 +136,9 @@ HEADERS += \
mediaformat.h \
avc/avcconfiguration.h \
generictagfield.h \
mp4/mpeg4descriptor.h
mp4/mpeg4descriptor.h \
avi/mediafourcc.h \
avi/bitmapinfoheader.h
LIBS += -lz