mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
VDR developer version 1.7.32 is now available at ftp://ftp.tvdr.de/vdr/Developer/vdr-1.7.32.tar.bz2 A 'diff' against the previous version is available at ftp://ftp.tvdr.de/vdr/Developer/vdr-1.7.31-1.7.32.diff MD5 checksums: 068ba78fd427694dcc480fe3b2d07148 vdr-1.7.32.tar.bz2 222f1e9b4d4edaa6fe57286409614cc7 vdr-1.7.31-1.7.32.diff WARNING: ======== This is a developer version. Even though I use it in my productive environment. I strongly recommend that you only use it under controlled conditions and for testing and debugging. The main focus of this version is on an improved frame detection code, and improvements to the cutting process. When cutting a recording, VDR now removes any "dangling" TS packets from the beginning of an editing sequence and pulls in any "pending" TS packets at the end of a sequence. It also fixes all timestamps and continuity counters. However, while the results look much better now in, for instance, Kaffeine, the TT S2-6400 still shows some video artifacts at the editing points, and the Mac video player sometimes totally chokes on edited material. I did spend a lot of time trying to find out what could still be wrong here, but couldn't come up with any new ideas. So I think it's now time to invite others to test this new cutting code, read the source code and try to find out what's still going wrong here. Maybe (hopefully ;-) it's just some stupid little error... ;-) From the HISTORY file: - Pressing the Play key during normal live viewing mode now opens the Recordings menu if there is no "last viewed" recording (thanks to Alexander Wenzel). The same behavior has been implemented for the Blue key in the main menu. - cIoThrottle::Engaged() is now also checked in cRemoveDeletedRecordingsThread::Action(), to suspend removing deleted recordings in case this is necessary to make room for new, ongoing recordings (suggested by Udo Richter). - The cThread constructor now has an additional boolean parameter that can be set to true to have this thread run at a lower priority. Plugin authors that use low priority threads may want to use this instead of the calls to SetPriority(19) and SetIOPriority(7). The priority of a thread ("low" or "high") is now logged when the thread starts. - Changed DTV_DVBT2_PLP_ID to DTV_STREAM_ID in dvbdevice.c to adapt to an incompatible change in DVB API 5.8 (reported by Derek Kelly). Removed the meanwhile obsolete definition of FE_CAN_TURBO_FEC. - Fixed some compiler warnings under gcc version 4.7.1. - Fixed setting the video format in the dvbhdffdevice (thanks to Torsten Lang). - Fixed 'make install' to not overwrite existing configuration files (thanks to Peter Münster). - Added including the Make.global and Make.config files to the dvbdhffdevice's libhdffcmd/Makefile. - Added options to build a 32-bit version of VDR on a 64-bit machine to Make.config.template. - Fixed handling VPS timers in case the running status of an event goes to '1' (not running) and later goes to '4' (running). - If a frame position in the 'marks' file of a recording doesn't point to an I-frame, it will now be shifted towards the next I-frame, either up or down, whichever is closer (suggested by Udo Richter). - Fixed a possible memory leak in SI::StructureLoop::getNextAsPointer() (reported by Sundararaj Reel). - Fixed handling timers in case an event is modified and "phased out" while the timer is recording. - Improved frame detection by parsing just far enough into the MPEG-4 NAL units to get the necessary information about frames and slices. - The initial syncing of the frame detector is now done immediately after the first complete GOP has been seen. This makes recordings and especially pausing live video start up to twice as fast as before. - Updated the Romanian OSD texts (thanks to Lucian Muresan). - Fixed handling the very last entry in a recording index. - The return type of cMarks::Add() has been changed to void, since due to the sorting of the list of marks the returned pointer might have pointed to a totally different mark. Besides, the return value was never actually used. - Improved editing TS recordings by + stripping dangling TS packets from the beginning of a sequence + including pending TS packets at the end of a sequence + fixing all timestamps and continuity counters + generating editing marks for the edited version in such a way that each cutting point is marked by an "end" and "begin" mark with the same offset + no longer generating an editing mark at the "end" of the edited recording (this was actually generated at the beginning of the last GOP, so that a subsequent edit would have cut off the last GOP) + no longer generating any editing marks if the edited recording results on just one single sequence + ignoring pairs of editing marks that are placed at exactly the same position of a recording when actually cutting the recording + not doing anything if the editing marks in place would result in the edited version being the same as the original recording - Editing marks can now be placed directly on top of each other, in which case they simply mark a position, but have no effect on the actual cutting process. - When positioned at an offset where two (or more) editing marks are placed on top of each other, the '4' key moves the first one of them to the left, while the '6' key moves the last one of them to the right. The '7' and '9' key handle multiple marks at the same place as if it were one single mark. - Modified editing marks are now written to disk whenever the replay progress display gets hidden (thanks to Christoph Haubrich).
523 lines
21 KiB
C++
523 lines
21 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2003 by Marcel Wiesweg *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* $Id: si.h 2.6 2012/10/15 11:56:06 kls Exp $
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#ifndef LIBSI_SI_H
|
|
#define LIBSI_SI_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "util.h"
|
|
#include "headers.h"
|
|
|
|
namespace SI {
|
|
|
|
enum TableId { TableIdPAT = 0x00, //program association section
|
|
TableIdCAT = 0x01, //conditional access section
|
|
TableIdPMT = 0x02, //program map section
|
|
TableIdTSDT = 0x03,//transport stream description section
|
|
TableIdNIT = 0x40, //network information, actual network section
|
|
TableIdNIT_other = 0x41, //network information section, other network
|
|
TableIdSDT = 0x42, //service description section
|
|
TableIdSDT_other = 0x46,
|
|
TableIdBAT = 0x4A, //bouquet association section
|
|
TableIdEIT_presentFollowing = 0x4E, //event information section
|
|
TableIdEIT_presentFollowing_other = 0x4F,
|
|
//range from 0x50 to 0x5F
|
|
TableIdEIT_schedule_first = 0x50,
|
|
TableIdEIT_schedule_last = 0x5F,
|
|
//range from 0x60 to 0x6F
|
|
TableIdEIT_schedule_Other_first = 0x60,
|
|
TableIdEIT_schedule_Other_last = 0x6F,
|
|
TableIdTDT = 0x70, //time date section
|
|
TableIdRST = 0x71, //running status section
|
|
TableIdST = 0x72, //stuffing section
|
|
TableIdTOT = 0x73, //time offset section
|
|
TableIdDIT = 0x7E, //discontinuity information section
|
|
TableIdSIT = 0x7F, //service information section
|
|
TableIdAIT = 0x74, //application information section
|
|
TableIdPremiereCIT = 0xA0 //premiere content information section
|
|
};
|
|
|
|
|
|
enum DescriptorTag {
|
|
// defined by ISO/IEC 13818-1
|
|
VideoStreamDescriptorTag = 0x02,
|
|
AudioStreamDescriptorTag = 0x03,
|
|
HierarchyDescriptorTag = 0x04,
|
|
RegistrationDescriptorTag = 0x05,
|
|
DataStreamAlignmentDescriptorTag = 0x06,
|
|
TargetBackgroundGridDescriptorTag = 0x07,
|
|
VideoWindowDescriptorTag = 0x08,
|
|
CaDescriptorTag = 0x09,
|
|
ISO639LanguageDescriptorTag = 0x0A,
|
|
SystemClockDescriptorTag = 0x0B,
|
|
MultiplexBufferUtilizationDescriptorTag = 0x0C,
|
|
CopyrightDescriptorTag = 0x0D,
|
|
MaximumBitrateDescriptorTag = 0x0E,
|
|
PrivateDataIndicatorDescriptorTag = 0x0F,
|
|
SmoothingBufferDescriptorTag = 0x10,
|
|
STDDescriptorTag = 0x11,
|
|
IBPDescriptorTag = 0x12,
|
|
// defined by ISO-13818-6 (DSM-CC)
|
|
CarouselIdentifierDescriptorTag = 0x13,
|
|
// 0x14 - 0x3F Reserved
|
|
// defined by ETSI (EN 300 468)
|
|
NetworkNameDescriptorTag = 0x40,
|
|
ServiceListDescriptorTag = 0x41,
|
|
StuffingDescriptorTag = 0x42,
|
|
SatelliteDeliverySystemDescriptorTag = 0x43,
|
|
CableDeliverySystemDescriptorTag = 0x44,
|
|
VBIDataDescriptorTag = 0x45,
|
|
VBITeletextDescriptorTag = 0x46,
|
|
BouquetNameDescriptorTag = 0x47,
|
|
ServiceDescriptorTag = 0x48,
|
|
CountryAvailabilityDescriptorTag = 0x49,
|
|
LinkageDescriptorTag = 0x4A,
|
|
NVODReferenceDescriptorTag = 0x4B,
|
|
TimeShiftedServiceDescriptorTag = 0x4C,
|
|
ShortEventDescriptorTag = 0x4D,
|
|
ExtendedEventDescriptorTag = 0x4E,
|
|
TimeShiftedEventDescriptorTag = 0x4F,
|
|
ComponentDescriptorTag = 0x50,
|
|
MocaicDescriptorTag = 0x51,
|
|
StreamIdentifierDescriptorTag = 0x52,
|
|
CaIdentifierDescriptorTag = 0x53,
|
|
ContentDescriptorTag = 0x54,
|
|
ParentalRatingDescriptorTag = 0x55,
|
|
TeletextDescriptorTag = 0x56,
|
|
TelephoneDescriptorTag = 0x57,
|
|
LocalTimeOffsetDescriptorTag = 0x58,
|
|
SubtitlingDescriptorTag = 0x59,
|
|
TerrestrialDeliverySystemDescriptorTag = 0x5A,
|
|
MultilingualNetworkNameDescriptorTag = 0x5B,
|
|
MultilingualBouquetNameDescriptorTag = 0x5C,
|
|
MultilingualServiceNameDescriptorTag = 0x5D,
|
|
MultilingualComponentDescriptorTag = 0x5E,
|
|
PrivateDataSpecifierDescriptorTag = 0x5F,
|
|
ServiceMoveDescriptorTag = 0x60,
|
|
ShortSmoothingBufferDescriptorTag = 0x61,
|
|
FrequencyListDescriptorTag = 0x62,
|
|
PartialTransportStreamDescriptorTag = 0x63,
|
|
DataBroadcastDescriptorTag = 0x64,
|
|
ScramblingDescriptorTag = 0x65,
|
|
DataBroadcastIdDescriptorTag = 0x66,
|
|
TransportStreamDescriptorTag = 0x67,
|
|
DSNGDescriptorTag = 0x68,
|
|
PDCDescriptorTag = 0x69,
|
|
AC3DescriptorTag = 0x6A,
|
|
AncillaryDataDescriptorTag = 0x6B,
|
|
CellListDescriptorTag = 0x6C,
|
|
CellFrequencyLinkDescriptorTag = 0x6D,
|
|
AnnouncementSupportDescriptorTag = 0x6E,
|
|
ApplicationSignallingDescriptorTag = 0x6F,
|
|
AdaptationFieldDataDescriptorTag = 0x70,
|
|
ServiceIdentifierDescriptorTag = 0x71,
|
|
ServiceAvailabilityDescriptorTag = 0x72,
|
|
// defined by ETSI (EN 300 468) v 1.7.1
|
|
DefaultAuthorityDescriptorTag = 0x73,
|
|
RelatedContentDescriptorTag = 0x74,
|
|
TVAIdDescriptorTag = 0x75,
|
|
ContentIdentifierDescriptorTag = 0x76,
|
|
TimeSliceFecIdentifierDescriptorTag = 0x77,
|
|
ECMRepetitionRateDescriptorTag = 0x78,
|
|
S2SatelliteDeliverySystemDescriptorTag = 0x79,
|
|
EnhancedAC3DescriptorTag = 0x7A,
|
|
DTSDescriptorTag = 0x7B,
|
|
AACDescriptorTag = 0x7C,
|
|
ExtensionDescriptorTag = 0x7F,
|
|
// Extension descriptors
|
|
ImageIconDescriptorTag = 0x00,
|
|
CpcmDeliverySignallingDescriptor = 0x01,
|
|
CPDescriptorTag = 0x02,
|
|
CPIdentifierDescriptorTag = 0x03,
|
|
T2DeliverySystemDescriptorTag = 0x04,
|
|
SHDeliverySystemDescriptorTag = 0x05,
|
|
SupplementaryAudioDescriptorTag = 0x06,
|
|
NetworkChangeNotifyDescriptorTag = 0x07,
|
|
MessageDescriptorTag = 0x08,
|
|
TargetRegionDescriptorTag = 0x09,
|
|
TargetRegionNameDescriptorTag = 0x0A,
|
|
ServiceRelocatedDescriptorTag = 0x0B,
|
|
|
|
// Defined by ETSI TS 102 812 (MHP)
|
|
// They once again start with 0x00 (see page 234, MHP specification)
|
|
MHP_ApplicationDescriptorTag = 0x00,
|
|
MHP_ApplicationNameDescriptorTag = 0x01,
|
|
MHP_TransportProtocolDescriptorTag = 0x02,
|
|
MHP_DVBJApplicationDescriptorTag = 0x03,
|
|
MHP_DVBJApplicationLocationDescriptorTag = 0x04,
|
|
// 0x05 - 0x0A is unimplemented this library
|
|
MHP_ExternalApplicationAuthorisationDescriptorTag = 0x05,
|
|
MHP_IPv4RoutingDescriptorTag = 0x06,
|
|
MHP_IPv6RoutingDescriptorTag = 0x07,
|
|
MHP_DVBHTMLApplicationDescriptorTag = 0x08,
|
|
MHP_DVBHTMLApplicationLocationDescriptorTag = 0x09,
|
|
MHP_DVBHTMLApplicationBoundaryDescriptorTag = 0x0A,
|
|
MHP_ApplicationIconsDescriptorTag = 0x0B,
|
|
MHP_PrefetchDescriptorTag = 0x0C,
|
|
MHP_DelegatedApplicationDescriptorTag = 0x0E,
|
|
MHP_ApplicationStorageDescriptorTag = 0x10,
|
|
MHP_SimpleApplicationLocationDescriptorTag = 0x15,
|
|
MHP_SimpleApplicationBoundaryDescriptorTag = 0x17,
|
|
// Premiere private Descriptor Tags
|
|
PremiereContentTransmissionDescriptorTag = 0xF2,
|
|
|
|
//a descriptor currently unimplemented in this library
|
|
//the actual value 0xFF is "forbidden" according to the spec.
|
|
UnimplementedDescriptorTag = 0xFF
|
|
};
|
|
|
|
enum DescriptorTagDomain { SI, MHP, PCIT };
|
|
|
|
enum RunningStatus { RunningStatusUndefined = 0,
|
|
RunningStatusNotRunning = 1,
|
|
RunningStatusStartsInAFewSeconds = 2,
|
|
RunningStatusPausing = 3,
|
|
RunningStatusRunning = 4
|
|
};
|
|
|
|
enum LinkageType { LinkageTypeInformationService = 0x01,
|
|
LinkageTypeEPGService = 0x02,
|
|
LinkageTypeCaReplacementService = 0x03,
|
|
LinkageTypeTSContainingCompleteNetworkBouquetSi = 0x04,
|
|
LinkageTypeServiceReplacementService = 0x05,
|
|
LinkageTypeDataBroadcastService = 0x06,
|
|
LinkageTypeRCSMap = 0x07,
|
|
LinkageTypeMobileHandover = 0x08,
|
|
LinkageTypeSystemSoftwareUpdateService = 0x09,
|
|
LinkageTypeTSContainingSsuBatOrNit = 0x0A
|
|
};
|
|
|
|
enum AudioType { AudioTypeUndefined = 0x00,
|
|
AudioTypeCleanEffects = 0x01,
|
|
AudioTypeHearingImpaired = 0x02,
|
|
AudioTypeVisualImpairedCommentary = 0x03
|
|
};
|
|
|
|
/* Some principles:
|
|
- Objects that return references to other objects contained in their data must make sure
|
|
that the returned objects have been parsed.
|
|
(the Loop subclasses take care of that.)
|
|
Note that this does not apply to Loops and Strings (their are never returned by reference, BTW).
|
|
*/
|
|
|
|
class Object : public Parsable {
|
|
public:
|
|
Object();
|
|
Object(CharArray &d);
|
|
//can only be called once since data is immutable
|
|
void setData(const unsigned char*data, int size, bool doCopy=true);
|
|
CharArray getData() { return data; }
|
|
//returns the valid flag which indicates if data is all right or errors have been encountered
|
|
bool isValid() { return data.isValid(); }
|
|
virtual int getLength() = 0;
|
|
protected:
|
|
CharArray data;
|
|
//is protected - not used for sections
|
|
template <class T> friend class StructureLoop;
|
|
void setData(CharArray &d);
|
|
//returns whether the given offset fits within the limits of the actual data
|
|
//The valid flag will be set accordingly
|
|
bool checkSize(int offset);
|
|
};
|
|
|
|
class Section : public Object {
|
|
public:
|
|
//convenience: sets data and parses if doParse
|
|
Section(const unsigned char *data, bool doCopy=true);
|
|
Section() {}
|
|
TableId getTableId() const;
|
|
virtual int getLength();
|
|
|
|
static int getLength(const unsigned char *d);
|
|
static TableId getTableId(const unsigned char *d);
|
|
};
|
|
|
|
class CRCSection : public Section {
|
|
public:
|
|
//convenience: sets data and parses if doParse
|
|
CRCSection(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
|
|
CRCSection() {}
|
|
bool isCRCValid();
|
|
//convenience: isValid+CheckParse
|
|
bool CheckCRCAndParse();
|
|
};
|
|
|
|
/* A section which has the ExtendedSectionHeader
|
|
(section_syntax_indicator==1) */
|
|
class NumberedSection : public CRCSection {
|
|
public:
|
|
NumberedSection(const unsigned char *data, bool doCopy=true) : CRCSection(data, doCopy) {}
|
|
NumberedSection() {}
|
|
int getTableIdExtension() const;
|
|
bool getCurrentNextIndicator() const;
|
|
int getVersionNumber() const;
|
|
int getSectionNumber() const;
|
|
int getLastSectionNumber() const;
|
|
bool moreThanOneSection() const { return getLastSectionNumber()>0; }
|
|
|
|
static int getTableIdExtension(const unsigned char *d);
|
|
};
|
|
|
|
class VariableLengthPart : public Object {
|
|
public:
|
|
//never forget to call this
|
|
void setData(CharArray d, int l) { Object::setData(d); checkSize(l); length=l; }
|
|
//convenience method
|
|
void setDataAndOffset(CharArray d, int l, int &offset) { Object::setData(d); checkSize(l); length=l; offset+=l; }
|
|
virtual int getLength() { return length; }
|
|
private:
|
|
int length;
|
|
};
|
|
|
|
class LoopElement : public Object {
|
|
};
|
|
|
|
class Descriptor : public LoopElement {
|
|
public:
|
|
virtual int getLength();
|
|
DescriptorTag getDescriptorTag() const;
|
|
|
|
static int getLength(const unsigned char *d);
|
|
static DescriptorTag getDescriptorTag(const unsigned char *d);
|
|
protected:
|
|
friend class DescriptorLoop;
|
|
//returns a subclass of descriptor according to the data given.
|
|
//The object is allocated with new and must be delete'd.
|
|
//setData() will have been called, CheckParse() not.
|
|
//if returnUnimplemetedDescriptor==true:
|
|
// Never returns null - maybe the UnimplementedDescriptor.
|
|
//if returnUnimplemetedDescriptor==false:
|
|
// Never returns the UnimplementedDescriptor - maybe null
|
|
static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor);
|
|
};
|
|
|
|
class Loop : public VariableLengthPart {
|
|
public:
|
|
class Iterator {
|
|
public:
|
|
Iterator() { i=0; }
|
|
void reset() { i=0; }
|
|
private:
|
|
template <class T> friend class StructureLoop;
|
|
friend class DescriptorLoop;
|
|
template <class T> friend class TypeLoop;
|
|
friend class ExtendedEventDescriptors;
|
|
int i;
|
|
};
|
|
protected:
|
|
virtual void Parse() {}
|
|
};
|
|
|
|
//contains LoopElements of one type only
|
|
template <class T> class StructureLoop : public Loop {
|
|
public:
|
|
//currently you must use a while-loop testing for hasNext()
|
|
//i must be 0 to get the first descriptor (with the first call)
|
|
bool getNext(T &obj, Iterator &it)
|
|
{
|
|
if (!isValid() || it.i >= getLength())
|
|
return false;
|
|
CharArray d=data;
|
|
d.addOffset(it.i);
|
|
T ret;
|
|
ret.setData(d);
|
|
ret.CheckParse();
|
|
if (!checkSize(ret.getLength()))
|
|
return false;
|
|
it.i+=ret.getLength();
|
|
obj=ret;
|
|
return true;
|
|
}
|
|
T* getNextAsPointer(Iterator &it)
|
|
{
|
|
if (!isValid() || it.i >= getLength())
|
|
return 0;
|
|
CharArray d=data;
|
|
d.addOffset(it.i);
|
|
T *ret=new T();
|
|
ret->setData(d);
|
|
ret->CheckParse();
|
|
if (!checkSize(ret->getLength())) {
|
|
delete ret;
|
|
return 0;
|
|
}
|
|
it.i+=ret->getLength();
|
|
return ret;
|
|
}
|
|
//bool hasNext(Iterator &it) { return getLength() > it.i; }
|
|
};
|
|
|
|
//contains descriptors of different types
|
|
class DescriptorLoop : public Loop {
|
|
public:
|
|
DescriptorLoop() { domain=SI; }
|
|
//i must be 0 to get the first descriptor (with the first call)
|
|
//All returned descriptors must be delete'd.
|
|
//returns null if no more descriptors available
|
|
Descriptor *getNext(Iterator &it);
|
|
//return the next descriptor with given tag, or 0 if not available.
|
|
//if returnUnimplemetedDescriptor==true:
|
|
// an UnimplementedDescriptor may be returned if the next matching descriptor is unimplemented,
|
|
// 0 will be returned if and only if no matching descriptor is found.
|
|
//if returnUnimplemetedDescriptor==false:
|
|
// if 0 is returned, either no descriptor with the given tag was found,
|
|
// or descriptors were found, but the descriptor type is not implemented
|
|
//In either case, a return value of 0 indicates that no further calls to this method
|
|
//with the iterator shall be made.
|
|
Descriptor *getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor=false);
|
|
//return the next descriptor with one of the given tags, or 0 if not available.
|
|
//if returnUnimplemetedDescriptor==true:
|
|
// returns 0 if and only if no descriptor with one of the given tags was found.
|
|
// The UnimplementedDescriptor may be returned.
|
|
//if returnUnimplemetedDescriptor==false:
|
|
// if 0 is returned, either no descriptor with one of the given tags was found,
|
|
// or descriptors were found, but none of them are implemented.
|
|
// The UnimplementedDescriptor will never be returned.
|
|
//In either case, a return value of 0 indicates that no further calls to this method
|
|
//with the iterator shall be made.
|
|
Descriptor *getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor=false);
|
|
//returns the number of descriptors in this loop
|
|
int getNumberOfDescriptors();
|
|
//writes the tags of the descriptors in this loop in the array,
|
|
// which must at least have the size getNumberOfDescriptors().
|
|
//The number of descriptors, i.e. getNumberOfDescriptors(), is returned.
|
|
// You can specify the array type (Descriptor tags are 8 Bit,
|
|
// you might e.g. choose a char, short, int or DescriptorTag array)
|
|
template <typename T> int getDescriptorTags(T *tags)
|
|
{
|
|
const unsigned char *p=data.getData();
|
|
const unsigned char *end=p+getLength();
|
|
int count=0;
|
|
while (p < end) {
|
|
tags[count++]=(T)Descriptor::getDescriptorTag(p);
|
|
p+=Descriptor::getLength(p);
|
|
}
|
|
return count;
|
|
}
|
|
protected:
|
|
Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor);
|
|
DescriptorTagDomain domain;
|
|
};
|
|
|
|
typedef uint8_t EightBit;
|
|
typedef uint16_t SixteenBit;
|
|
typedef uint32_t ThirtyTwoBit;
|
|
typedef uint64_t SixtyFourBit;
|
|
|
|
template <typename T> class TypeLoop : public Loop {
|
|
public:
|
|
int getCount() { return getLength()/sizeof(T); }
|
|
T operator[](const int index) const
|
|
{
|
|
switch (sizeof(T)) {
|
|
case 1:
|
|
return data[index];
|
|
case 2:
|
|
return data.TwoBytes(index);
|
|
case 4:
|
|
return data.FourBytes(index);
|
|
case 8:
|
|
return (SixtyFourBit(data.FourBytes(index)) << 32) | data.FourBytes(index+4);
|
|
default:
|
|
return 0; // just to avoid a compiler warning
|
|
}
|
|
return 0; // just to avoid a compiler warning
|
|
}
|
|
T getNext(Iterator &it) const
|
|
{
|
|
T ret=operator[](it.i);
|
|
it.i+=sizeof(T);
|
|
return ret;
|
|
}
|
|
bool hasNext(Iterator &it) { return isValid() && (getLength() > it.i); }
|
|
};
|
|
|
|
class MHP_DescriptorLoop : public DescriptorLoop {
|
|
public:
|
|
MHP_DescriptorLoop() { domain=MHP; }
|
|
};
|
|
|
|
//Premiere Content Information Table
|
|
class PCIT_DescriptorLoop : public DescriptorLoop {
|
|
public:
|
|
PCIT_DescriptorLoop() { domain=PCIT; }
|
|
};
|
|
|
|
//The content of the ExtendedEventDescriptor may be split over several
|
|
//descriptors if the text is longer than 256 bytes.
|
|
//The following classes provide base functionality to handle this case.
|
|
class GroupDescriptor : public Descriptor {
|
|
public:
|
|
virtual int getDescriptorNumber() = 0;
|
|
virtual int getLastDescriptorNumber() = 0;
|
|
};
|
|
|
|
class DescriptorGroup {
|
|
public:
|
|
DescriptorGroup(bool deleteOnDesctruction=true);
|
|
~DescriptorGroup();
|
|
void Add(GroupDescriptor *d);
|
|
void Delete();
|
|
int getLength() { return length; }
|
|
GroupDescriptor **getDescriptors() { return array; }
|
|
bool isComplete(); //if all descriptors have been added
|
|
protected:
|
|
int length;
|
|
GroupDescriptor **array;
|
|
bool deleteOnDesctruction;
|
|
};
|
|
|
|
class String : public VariableLengthPart {
|
|
public:
|
|
//A note to the length: getLength() returns the length of the raw data.
|
|
//The text may be shorter. Its length can be obtained with one of the
|
|
//getText functions and strlen.
|
|
|
|
//returns text. Data is allocated with new and must be delete'd by the user.
|
|
char *getText();
|
|
//copies text into given buffer.
|
|
//a buffer of size getLength()+1 is guaranteed to be sufficiently large.
|
|
//In most descriptors the string length is an 8-bit field,
|
|
//so the maximum there is 256.
|
|
//returns the given buffer for convenience.
|
|
//The emphasis marks 0x86 and 0x87 are still available.
|
|
char *getText(char *buffer, int size);
|
|
//The same semantics as for getText(char*) apply.
|
|
//The short version of the text according to ETSI TR 101 211 (chapter 4.6)
|
|
//will be written into the shortVersion buffer (which should, therefore, have the same
|
|
//length as buffer). If no shortVersion is available, shortVersion will contain
|
|
//an empty string.
|
|
//The emphasis marks 0x86 and 0x87 are still available in buffer, but not in shortVersion.
|
|
char *getText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion);
|
|
protected:
|
|
virtual void Parse() {}
|
|
void decodeText(char *buffer, int size);
|
|
void decodeText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion);
|
|
};
|
|
|
|
// Call this function to set the system character table. CharacterTable is a string
|
|
// like "iso8859-15" or "utf-8" (case insensitive).
|
|
// Returns true if the character table was recognized.
|
|
bool SetSystemCharacterTable(const char *CharacterTable);
|
|
// Determines the character table used in the given buffer and returns
|
|
// a string indicating that table. If no table can be determined, the
|
|
// default ISO6937 is returned. If a table can be determined, the buffer
|
|
// and length are adjusted accordingly.
|
|
const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte = NULL);
|
|
bool convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode);
|
|
bool systemCharacterTableIsSingleByte(void);
|
|
|
|
} //end of namespace
|
|
|
|
#endif //LIBSI_SI_H
|