/************************************************************* * mpgtx an mpeg toolbox * * by Laurent Alacoque * * (c) 2001 * * You may copy, modify and redistribute this * * source file under the terms of the GNU Public License * ************************************************************/ #ifndef __mpeg_hh_ #define __mpeg_hh_ #include "common.hh" #include "mpegOut.hh" // [laureck] Aug 2002 // We really should find its place for the following (any idea Phil ?) : typedef struct { // this stores the junk header of mpeg files, in case someone needs it later off_t size; byte *buf; } header_buf; /** * * @return pointer to the junk */ header_buf *readHeader(FILE *myMpegfile, off_t offset, int rw); typedef int PID; class mpeg_descriptors { public: mpeg_descriptors() { video_coding_version=-1; audio_coding_version=-1; CA=-1; CA_PID=-1; lang_audio_type=-1; languages=0; copyright=false; n_unhandled_desc=0; } ~mpeg_descriptors() { if (languages) delete[] languages; } void PrintInfos(char* prefix); int video_coding_version; int audio_coding_version; int CA; PID CA_PID; int lang_audio_type; char* languages; bool copyright; byte n_unhandled_desc; }; typedef struct ES_t { PID pid; byte type; ES_t *next; mpeg_descriptors descs; FILE* demuxFile; bool demuxFileOk; } EStream; typedef struct t_prog { EStream *TStreams; int nstreams; int prog_num; mpeg_descriptors descs; } program; class mpeg; //#define MAX_PROGS 100 //helper class that carries transport stream infos class transport { friend class mpeg; friend class demuxer; public : transport(); ~transport(); protected: void delete_programs(); void delete_ES(EStream* stream); void PrintInfos(); program* programs; int n_progs; int n_audio_streams; int n_video_streams; int n_other_streams; PID network_PID; PID* PMT_PIDs; int n_PMT_PIDs; int read_pmts; }; class mpeg { friend class mpegSystemOut; friend class demuxer; protected: // disallow basic constructors mpeg(){}; // Functions // General ToolBox /** * Gives a byte from address offset. * If offset is out of buffer, it creates new buffer beginning on offset * and load mpeg file in for forward operations. * * @param offset address to get byte * @return byte value from offset */ byte GetByte(off_t offset); /** * Gives a byte from address offset. * If offset is out of buffer, it creates new buffer ending on offset * and load mpeg file in for backward operations. * * @param offset address to get byte * @return byte value from offset */ byte bdGetByte(off_t offset); bool EnsureMPEG(off_t offset,marker mark); double ReadTS (off_t offset); double ReadTSMpeg2(off_t offset); long ReadPACKMuxRate(off_t offset); /** * find any marker. * find next 0x 00 00 01 xx sequence * * @param from start address of search * @return offset of found mark or -1 on error */ off_t FindNextMarker(off_t from); /** Searchs forward for any next marker, change mark accordingly. * find next 0x 00 00 01 xx sequence and set mark = xx * * @param from start address of search * @param mark pointer to mark to change * @return offset of found mark or -1 on error */ off_t FindNextMarker(off_t from, marker* mark); /** Searchs backward for any next marker, change mark accordingly. * find next 0x 00 00 01 xx sequence and set mark = xx * * @param from start address of search * @param mark pointer to mark to change * @return offset of found mark or -1 on error */ off_t bdFindNextMarker(off_t from, marker* mark); /** Prints every timestamp that follows a "0x 00 00 01 kind" sequence. * time stamp format depends on mpeg_version * * @param kind header mark of time stamp headers */ void print_all_ts(byte kind); /** Checks time line of increasing time stamps and return amount of breaks. * * @param kind header mark of time stamp headers * @return amount of breaks in time line */ int CheckTimeline(byte kind); public: /** * Constuctor. * Create a mpeg object from given file * * @param filename MPEG file to read * @param verbosity Amount of process messages: * mpeg_SILENT suppress all messages * mpeg_VERBOSE additional error messages * other normal process messages */ mpeg(const char* filename,int verbosity=mpeg_SILENT); ~mpeg(); // General ToolBox /** * Prints infos about MPEG stream to stdout. * Infos depending on MpegType: * mpeg_AUDIO: duration, version, layer, bitrate, sampling rate, frame lengh, * mode, emphasis, copyright, original/copy, ID3v1 tag * * mpeg_VIDEO: duration, aspect ratio, interlace, video format, display size, * frame rate, bit rate, user data * * mpeg_SYSTEM: infos above if available * * mpeg_TRANSPORT: call transport::PrintInfos() * */ void PrintInfos(); bool has_audio() {return HasAudio;} bool has_video() {return HasVideo;} off_t Size() {return FileSize;} const char* Name() {return FileName;} int Version() {return mpeg_version;} /** * Compare attributes of this and another MPEG * * @param peer pointer to the other MPEG * @return true if they fit, false otherwise */ bool Match(mpeg* peer); /// gets audio duration, video duration or zero (first valid will serve, of course ;-) float Duration(); /** * Calls mpeg::GetByte(). * * @param offset address to give to GetByte() * @return a byte got from GetByte() */ byte Byte(off_t offset); /** search forward for specific marker. * find next 0x 00 00 01 mark sequence * * @param from start address of search * @param mark mark to look for * @return offset of found marker or -1 on error */ off_t FindNextMarker(off_t from, marker mark); /** search backward for specific marker. * find next 0x 00 00 01 mark sequence * * @param from start address of search * @param mark mark to look for * @return offset of found marker or -1 on error */ off_t bdFindNextMarker(off_t from, marker mark); /** gets two byte from address and next one. * * @param offset address of higher byte, offset+1 is lower byte * @return two byte value of offset and offset+1 */ unsigned short int GetSize(off_t offset); /** * Converts seconds in a String HH:MM:SS.xxs * * @param HMS char array (min. 13 bytes) * @param duration in seconds */ void SecsToHMS(char* HMS, float duration); // Audio ToolBox /// check if audio is present after myoffset bool ParseAudio(off_t myoffset); /// check if ID3v2 tag is present and audio follows. bool ParseID3(); bool PrintID3(); off_t FindMatchingAudio(off_t myoffset); off_t bdFindMatchingAudio(off_t myoffset); bool MatchAudio(off_t myoffset); // Video ToolBox bool ParseVideo(off_t myoffset); bool ParseExtension(off_t myoffset); bool ParseSequenceExt(off_t myoffset); bool ParseSequenceDisplayExt(off_t myoffset); bool ParseUserData(off_t myoffset); // System ToolBox bool ParseSystem(); bool ParseSystemPacket(off_t startofpacket, off_t startofpack); bool ParseSystemHeader(off_t myoffset); off_t SkipPacketHeader(off_t myoffset); void ParseFramesInGOP(off_t offset); bool ParseRIFF(); bool ParseTransportStream(off_t offset); void ParseCAT(off_t offset); void ParsePAT(off_t offset); void ParsePMT(off_t offset); off_t ParseDescriptor(off_t offset, mpeg_descriptors* target); void DescCA(off_t offset, mpeg_descriptors* target); void DescLang(off_t offset, mpeg_descriptors* target); long Read12bitLength(off_t offset); long Read2Bytes(off_t offset); long ReadPID(off_t offset); PID NextTrPacket(off_t* offset, off_t* payload_start, off_t* payload_end); /// file handle (I hate iostream and I can't use read/write on windows) FILE* MpegFile; /// how much we speak int Verboseness; // mpeg Internals to be filled by constructor bool HasAudio,HasVideo; bool composite,editable; off_t FileSize; char* FileName; int MpegType; // audio internals mpgtx_audio* Audio; byte n_audio; // video internals mpgtx_video* Video; byte n_video; /// system internals mpgtx_system* System; /// transport stream internals transport* Transport; // extentions sequence_ext* SExt; display_ext* DExt; user_data* UData; /// start with id3v2 tag bool start_with_id3; /// for mpeg 1/ mpeg2 byte mpeg_version; // for GetByte off_t buffstart; off_t buffend; byte* buffer; }; typedef struct { char* file; off_t from; float sfrom; off_t to; float sto; bool from_included; bool to_included; bool until_file_size; bool unit_is_second; mpeg* mpegfile; } chunk; #endif // __mpeg_hh_