X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Flibzmpeg3%2Flibzmpeg3.h;fp=cinelerra-5.1%2Flibzmpeg3%2Flibzmpeg3.h;h=48414cdc5898724bdc41f186724297f77e7c985d;hp=0000000000000000000000000000000000000000;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b diff --git a/cinelerra-5.1/libzmpeg3/libzmpeg3.h b/cinelerra-5.1/libzmpeg3/libzmpeg3.h new file mode 100644 index 00000000..48414cdc --- /dev/null +++ b/cinelerra-5.1/libzmpeg3/libzmpeg3.h @@ -0,0 +1,3106 @@ +#ifndef LIBMPEG3_H +#define LIBMPEG3_H + +/* for quicktime build */ +#define MAXFRAMESAMPLES 65536 +#define ZDVB +#define USE_FUTEX + +#include +#define __STDC_LIMIT_MACROS +#include + +typedef int (*zthumbnail_cb)(void *p, int trk); +typedef int (*zcc_text_cb)(int sid, int id, int sfrm, int efrm, const char *txt); + +#ifdef __cplusplus +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_FUTEX +#include +#endif + +extern "C" { +#include "a52dec-0.7.3/include/a52.h" +} + +#define ZMPEG3_MAJOR 2 +#define ZMPEG3_MINOR 0 +#define ZMPEG3_RELEASE 0 +#define ZRENDERFARM_FS_PREFIX "vfs://" + +#define ZIO_SINGLE_ACCESS zfs_t::io_SINGLE_ACCESS +#define ZIO_UNBUFFERED zfs_t::io_UNBUFFERED +#define ZIO_NONBLOCK zfs_t::io_NONBLOCK +#define ZIO_SEQUENTIAL zfs_t::io_SEQUENTIAL +#define ZIO_THREADED zfs_t::io_THREADED +#define ZIO_ERRFAIL zfs_t::io_ERRFAIL +#define ZIO_RETRIES 1 + +#define TOC_SAMPLE_OFFSETS zmpeg3_t::show_toc_SAMPLE_OFFSETS +#define TOC_AUDIO_INDEX zmpeg3_t::show_toc_AUDIO_INDEX +#define TOC_FRAME_OFFSETS zmpeg3_t::show_toc_FRAME_OFFSETS + +#define ZMPEG3_PROC_CPUINFO "/proc/cpuinfo" +#if BYTE_ORDER == LITTLE_ENDIAN +#define ZMPEG3_LITTLE_ENDIAN 1 +#else +#define ZMPEG3_LITTLE_ENDIAN 0 +#endif + +// Combine the pid and the stream id into one unit +#define CUSTOM_ID(pid, stream_id) (((pid << 8) | stream_id) & 0xffff) +#define CUSTOM_ID_PID(id) (id >> 8) +#define CUSTOM_ID_STREAMID(id) (id & 0xff) + +#ifndef ZMAX +#define ZMAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef ZMIN +#define ZMIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef isizeof +#define isizeof(x) ((int)sizeof(x)) +#endif +#ifndef lengthof +#define lengthof(x) ((int)(sizeof(x)/sizeof(x[0]))) +#endif + +#define zlikely(x) __builtin_expect((x),1) +#define zunlikely(x) __builtin_expect((x),0) + +#if defined(__x86_64__) +#define _LD "%ld" +#define _LDv(v) "%" #v "ld" +#define _LU "%lu" +#define _LUv(v) "%" #v "lu" +#define _LX "%lx" +#define _LXv(v) "%" #v "lx" +#else +#define _LD "%lld" +#define _LDv(v) "%" #v "lld" +#define _LU "%llu" +#define _LUv(v) "%" #v "llu" +#define _LX "%llx" +#define _LXv(v) "%" #v "llx" +#endif +#define bcd(n) ((((n)>>4)&0x0f)*10+((n)&0x0f)) + +#define new_memset(s) \ + void *operator new(size_t n) { \ + void *t = (void*) new char[n]; \ + memset(t,s,n); \ + return t; \ + } \ + void operator delete(void *t,size_t n) { \ + delete[](char*)t; \ + } \ + void *operator new[](size_t n) { \ + void *t = (void*) new char[n]; \ + memset(t,s,n); \ + return t; \ + } \ + void operator delete[](void *t,size_t n) { \ + delete[](char*)t; \ + } + +#define znew(T,n) ((T*)memset(new T[n],0,(n)*sizeof(T))) +#define zmsg(fmt) printf("%s: " fmt, __func__) +#define zmsgs(fmt,args...) printf("%s: " fmt, __func__, args) +#define zerr(fmt) fprintf(stderr,"%s:err " fmt, __func__) +#define zerrs(fmt,args...) fprintf(stderr,"%s:err " fmt, __func__, args) +#define perr(fmt) do { char msg[512]; \ + snprintf(&msg[0],sizeof(msg), "%s: " fmt,__func__); perror(&msg[0]); \ +} while(0) +#define perrs(fmt,args...) do { char msg[512]; \ + snprintf(&msg[0],sizeof(msg), "%s: " fmt,__func__,args); perror(&msg[0]); \ +} while(0) + +class zmpeg3_t; + +class zmpeg3_t { +public: + new_memset(0); + class zlock_t; + class zblock_t; + class zrwlock_t; + class fs_t; + class bits_t; + class index_t; + class bitfont_t; + class timecode_t; + class audio_t; + class slice_buffer_t; + class video_t; + class slice_decoder_t; + class subtitle_t; + class demuxer_t; + class cacheframe_t; + class cache_t; + class atrack_t; + class vtrack_t; + class strack_t; +#ifdef ZDVB + class dvb_t; +#endif + + enum { + // Error codes for the error_return variable + ERR_UNDEFINED_ERROR = 1, + ERR_INVALID_TOC_VERSION = 2, + ERR_TOC_DATE_MISMATCH = 3, + + TOC_PREFIX = 0x544f4320, + // This decreases with every new version + TOC_VERSION = 0x000000f9, + ID3_PREFIX = 0x494433, + IFO_PREFIX = 0x44564456, + // First byte to read when opening a file + START_BYTE = 0x0, + // Bytes read by mpeg3io at a time + MAX_IO_SIZE = 0x10000, + IO_SIZE = 0x80000, + SEQ_IO_SIZE = 0xc00000, + MAX_TS_PROBE = 0x800000, + MAX_PGM_PROBE = 0x800000, + // Largest possible packet + RAW_SIZE = 0x400000, + RIFF_CODE = 0x52494646, + BD_PACKET_SIZE = 192, + TS_PACKET_SIZE = 188, + DVD_PACKET_SIZE = 0x800, + ERR_PACKET_SIZE = 0x800, + IO_ERR_LIMIT = 2, + SYNC_BYTE = 0x47, + PROGRAM_END_CODE = 0x000001b9, + PACK_START_CODE = 0x000001ba, + SEQUENCE_START_CODE = 0x000001b3, + SEQUENCE_END_CODE = 0x000001b7, + SYSTEM_START_CODE = 0x000001bb, + STRLEN = 1024, + // Maximum number of PIDs in one stream + PIDMAX = 256, + PROGRAM_ASSOCIATION_TABLE = 0x00, + CONDITIONAL_ACCESS_TABLE = 0x01, + PACKET_START_CODE_PREFIX = 0x000001, + // NAV/PRIVATE_STREAM_2 are the same id + PRIVATE_STREAM_2 = 0xbf, + NAV_PACKET_STREAM = 0xbf, + NAV_PCI_BYTES = 0x3d3, + NAV_DSI_BYTES = 0x3f9, + NAV_PCI_SSID = 0x00, + NAV_DSI_SSID = 0x01, + NAV_SRI_END_OF_CELL = 0x3fffffff, + PADDING_STREAM = 0xbe, + GOP_START_CODE = 0x000001b8, + PICTURE_START_CODE = 0x00000100, + EXT_START_CODE = 0x000001b5, + USER_START_CODE = 0x000001b2, + SLICE_MIN_START = 0x00000101, + SLICE_MAX_START = 0x000001af, + AC3_START_CODE = 0x0b77, + PCM_START_CODE = 0x7f7f807f, + MAX_CPUS = 256, + MAX_STREAMZ = 0x10000, + MAX_PACKSIZE = 262144, + MAX_CACHE_FRAMES = 128, + // Maximum number of complete subtitles to buffer in a subtitle track + // or number of incomplete subtitles to buffer in demuxer. + MAX_SUBTITLES = 16, + // Positive difference before declaring timecodes discontinuous + CONTIGUOUS_THRESHOLD = 10 , + // Minimum number of seconds before interleaving programs + PROGRAM_THRESHOLD = 5 , + // Number of frames difference before absolute seeking + SEEK_THRESHOLD = 16 , + // Size of chunk of audio in table of contents + AUDIO_CHUNKSIZE = 0x10000 , + // Minimum amount of data required to read a video header in streaming mode. + VIDEO_STREAM_SIZE = 0x100, + // Number of samples in audio history + AUDIO_HISTORY = 0x100000 , + // max number of samples returned by decoder per input frame + AUDIO_MAX_DECODE = 0x800 , + // Range to scan for pts after byte seek + PTS_RANGE = 0x100000, + // stream type + FT_PROGRAM_STREAM = 0x0001, + FT_TRANSPORT_STREAM = 0x0002, + FT_AUDIO_STREAM = 0x0004, + FT_VIDEO_STREAM = 0x0008, + FT_IFO_FILE = 0x0010, + FT_BD_FILE = 0x0020, + SUBTITLE_HOLD_TIME = 3, + CCAPTION_HOLD_TIME = 15, + }; + + enum color_model { + // All color models supported for read_frame + cmdl_BGR888=0, + cmdl_BGRA8888=1, + cmdl_RGB565=2, + cmdl_RGB888=3, + cmdl_RGBA8888=4, + cmdl_RGBA16161616=5, + // Color models for the 601 to RGB conversion + // 601 not implemented for scalar code + cmdl_601_BGR888=7, + cmdl_601_BGRA8888=8, + cmdl_601_RGB888=9, + cmdl_601_RGBA8888=10, + cmdl_601_RGB565=11, + // next 2 are supported color models for read_yuvframe + // also YVU420P/YVU422P with uv output_row ptrs reversed for read_frame + cmdl_YUV420P=12, + cmdl_YUV422P=13, + // the rest are supported color models for read_frame + cmdl_601_YUV420P=14, + cmdl_601_YUV422P=15, + cmdl_UYVY=16, + cmdl_YUYV=17, + cmdl_601_UYVY=18, + cmdl_601_YUYV=19, + cmdl_YUV888=20, + cmdl_YUVA8888=21, + cmdl_601_YUV888=22, + cmdl_601_YUVA8888=23, + }; + + // Values for audio input/output formats + enum audio_format { + afmt_IGNORE=-1, + afmt_UNKNOWN=0, + afmt_MPEG=1, + afmt_AC3=2, + afmt_PCM=3, + afmt_AAC=4, + afmt_JESUS=5, + + atyp_NONE=0, + atyp_DOUBLE=1, + atyp_FLOAT=2, + atyp_INT=3, + atyp_SHORT=4, + }; + + // Table of contents sections + enum toc_section_type { + toc_FILE_TYPE_PROGRAM=0, + toc_FILE_TYPE_TRANSPORT=1, + toc_FILE_TYPE_AUDIO=2, + toc_FILE_TYPE_VIDEO=3, + toc_STREAM_AUDIO=4, + toc_STREAM_VIDEO=5, + toc_STREAM_SUBTITLE=6, + toc_OFFSETS_AUDIO=7, + toc_OFFSETS_VIDEO=8, + toc_ATRACK_COUNT=9, + toc_VTRACK_COUNT=10, + toc_STRACK_COUNT=11, + toc_TITLE_PATH=12, + toc_IFO_PALETTE=13, + toc_FILE_INFO=14, + toc_IFO_PLAYINFO=15, + toc_SRC_PROGRAM=16, + }; + + +#ifdef USE_FUTEX +#define ZMPEG3_ZLOCK_INIT zzlock_t() + class zloc_t { + protected: + volatile int loc; + int zfutex(int op, int val, timespec *time=0) { + return syscall(SYS_futex,&loc,op,val,time,0,0); + } + int zyield(); + int zgettid(); + public: + int zwake(int nwakeups); + int zwait(int val); + int zwait() { return zwait(loc); } + static void zincr(volatile int &v) { /* atomic(++v) */ + asm ( " lock incl %1\n" : "+m" (v) :: ); + } + static void zdecr(volatile int &v) { /* atomic(--v) */ + asm ( " lock decl %1\n" : "+m" (v) :: ); + } + static char tdecr(volatile int &v) { + char ret; /* ret = atomic(--loc >= 0 ? 1 : 0) */ + asm ( " lock decl %1\n setge %0\n" : "=r" (ret), "+m" (v) :: ); + return ret; + } + static char tincr(volatile int &v) { + char ret; /* ret = atomic(++loc > 0 ? 1 : 0) */ + asm ( " lock incl %1\n setg %0\n" : "=r" (ret), "+m" (v) :: ); + return ret; + } + static int zcmpxchg(int old, int val, volatile int &v) { + int ret = old; + asm volatile( " lock\n cmpxchgl %2,%1\n" + : "+a" (ret), "+m" (v) : "r" (val) : "memory" ); + return ret; + } + static int zxchg(int val, volatile int &v) { + asm volatile( " xchgl %0,%1\n" + : "+r" (val), "+m" (v) :: "memory" ); + return val; + } + static int zadd(int n, volatile int &v) { + int old, mod, val; + do { val = (old=v)+n; mod = zcmpxchg(old,val,v); + } while( mod != old ); + return val; + } + static void zmfence() { + asm volatile ( " mfence\n" ::: "memory" ); + } + + zloc_t() : loc(-1) {} + ~zloc_t() {} + }; + + class zlock_t : zloc_t { + protected: + friend class zblock_t; + friend class zrwlock_t; + int zlock(int v); + int zunlock(int nwakeups=1); + static int zemsg1(); + public: + int lock() { + int v, ret = zunlikely( (v=zcmpxchg(-1,0,loc)) >= 0 ) ? zlock(v) : 0; + return ret; + } + int unlock() { + if( zunlikely(loc < 0) ) { return zemsg1(); } + int v, ret = zunlikely( (v=zcmpxchg(0,-1,loc)) != 0 ) ? zunlock() : 0; + return ret; + } + zlock_t() {} + ~zlock_t() {} + }; + + class zblock_t : zlock_t { + public: + void block() { loc = 0; zwait(0); } + void unblock() { if( !loc ) { loc = -1; zwake(INT_MAX); } } + zblock_t() {} + ~zblock_t() {} + }; + + class zrwlock_t : zloc_t { + zlock_t lk; + void zenter(); + void zleave(); + void zwrite_enter(int r); // r==0: do nothing, r>0: write_lock + void zwrite_leave(int r); // r<0: write_lock while read_lock + public: + void enter() { zincr(loc); if( zunlikely( lk.loc >= 0 ) ) zenter(); } + void leave() { if( zunlikely( !tdecr(loc) ) ) zleave(); } + void write_enter(int r=1) { if( r ) zwrite_enter(r); } + void write_leave(int r=1) { if( r ) zwrite_leave(r); } + zrwlock_t() {} + ~zrwlock_t() {} + }; + +#else +#define ZMPEG3_ZLOCK_INIT { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER } + + class zlock_t { + protected: + pthread_mutex_t zlock; + public: + void lock() { pthread_mutex_lock(&zlock); } + void unlock() { pthread_mutex_unlock(&zlock); } + zlock_t() { pthread_mutex_init(&zlock, 0); } + ~zlock_t() { pthread_mutex_destroy(&zlock); } + }; + + class zblock_t { + pthread_mutex_t zblock; + pthread_cond_t cond; + public: + zblock_t() { + pthread_mutex_init(&zblock, 0); + pthread_cond_init(&cond, 0); + } + ~zblock_t() { + pthread_mutex_destroy(&zblock); + pthread_cond_destroy(&cond); + } + void block() { + pthread_mutex_lock(&zblock); + pthread_cond_wait(&cond, &zblock); + pthread_mutex_unlock(&zblock); + } + void unblock() { pthread_cond_broadcast(&cond); } + }; + + class zrwlock_t : zlock_t { + volatile pthread_t blocking; + volatile int users; + zlock_t lk; + pthread_cond_t cond; + void wait() { pthread_cond_wait(&cond, &zlock); } + void wake() { pthread_cond_signal(&cond); } + void zwrite_enter(int r); + void zwrite_leave(int r); + public: + void enter(); + void leave(); + void write_enter(int r=1) { if( r ) zwrite_enter(r); } + void write_leave(int r=1) { if( r ) zwrite_leave(r); } + int count() { return users; } + + zrwlock_t() { pthread_cond_init(&cond, 0); } + ~zrwlock_t() { pthread_cond_destroy(&cond); } + }; + +#endif + + // I/O + + // Filesystem structure + // We buffer in IO_SIZE buffers. Stream IO would require back + // buffering a buffer since the stream must be rewound for packet headers, + // sequence start codes, format parsing, decryption, and mpeg3cat. + + class fs_t { + int sync() { + return buffer->sync(current_byte); + } + int enter() { + buffer->lock(); + return sync(); + } + void leave() { + buffer->unlock(); + } + public: + new_memset(0); + class css_t; + + class css_t { // Encryption object + public: + class playkey_t; + class keytext_t; + + typedef uint8_t key_t[5]; + typedef uint8_t blk_t[5]; + class playkey_t { + public: + int offset; + key_t key; + }; + class keytext_t { + public: + keytext_t *lt, *rt; + uint8_t ktxt[4], ctxt[10]; + keytext_t(const uint8_t *kp, const uint8_t *cp) { + lt = rt = 0; + memcpy(&ktxt[0],kp,sizeof(ktxt)); + memcpy(&ctxt[0],cp,sizeof(ctxt)); + } + ~keytext_t() {} + } *key_root; + void add_key_text(const uint8_t *kp, const uint8_t *cp); + uint8_t *find_key_text(const uint8_t *kp); + int attack_pattern(uint8_t const *sec, uint8_t *key); + void del_keytexts(keytext_t *p); + private: + void css_engine(int v,uint8_t const *input, blk_t &output); + void crypt_key1(int v, blk_t &key); + void crypt_key2(blk_t &key); + void crypt_bus_key(blk_t &key); + int get_asf(); + int authenticate_drive(key_t &key); + int hostauth(dvd_authinfo *ai); + int get_title_key(key_t &key); + int get_disk_key(key_t &key); + int validate(int do_title); + int validate_path(int do_title); + int decrypt_title_key(uint8_t *dkey, uint8_t *tkey); + public: + key_t key1; + key_t key2; + key_t keycheck; + key_t title_key; + int lba, fsz, agid, encrypted; + char device_path[STRLEN]; // Device where the file is located + uint8_t disk_key[DVD_PACKET_SIZE]; + char challenge[10]; + int varient; + int fd; + char path[STRLEN]; + + css_t(); + ~css_t(); + + int get_keys(char *fpath); + int decrypt_packet(uint8_t *sector, int offset); + int crack_title_key(key_t &ckey, key_t &tkey); + } css; + + enum access_strategy { + io_SINGLE_ACCESS=1, + io_UNBUFFERED=2, + io_NONBLOCK=4, + io_SEQUENTIAL=8, + io_THREADED=16, + io_ERRFAIL=32, + }; + + class buffer_t { + void unblock(); + void block(); + void reader(); + static void *reader(void *the_buffer); + void writer(); + static void *writer(void *the_buffer); + int64_t read_in(int64_t len); + int read_fin(int64_t len); + int wait_in(int64_t pos); + int seek_in(int64_t pos); + int seek_to(int64_t pos, int64_t len); + int read_to(int64_t pos); + zmpeg3_t *src; + zlock_t io_lock; // buffer_t access lock + zblock_t io_block; // buffer_t access block + int errs; // number of consecutive errors + uint8_t *data; // Readahead buffer + int alloc; // buffer byte allocate + int size; // defined bytes in buffer + int in; // buffer byte in, owned by read_in + int out; // buffer byte out + int64_t out_pos; // file offset next byte from last read + int64_t file_pos; // file position of next readable byte + int64_t file_nudge; // sync position offset + int fin; // locked version of in, synced with file_pos + pthread_t the_reader; // reader thread if io_THREADED + pthread_t the_writer; // writer thread if io_THREADED and recording + pthread_t owner; // for debugging + int restarted; // reader restarted + int reader_done; // reader thread termination flag + int writer_done; // writer thread termination flag + int wout; // write record file buffer byte out + int64_t write_pos; // file_pos written to recd_fd + zblock_t write_lock; // write record block + public: + new_memset(0); + buffer_t(zmpeg3_t *zsrc, int access); + ~buffer_t(); + int access_type; // io_ flags + int paused; // reader discard data + int do_restart; // reader restart buffer + int ref_count; // number of fs_t referencing this + int open_count; // number of is_open fs_t + int fd; // unbuffered file descriptor + FILE *fp; // buffered file handle + int open_file(char *path); + void close_file(); + void reset(); + void restart(int lk=1); + int64_t tell() { return out_pos; } + int64_t file_tell() { return file_pos; } + int sync(int64_t pos); + int errors() { return errs; } + uint32_t next_byte() { + return data[out]; + } + uint32_t get_byte() { + uint32_t result = next_byte(); + if( ++out >= alloc ) out = 0; + ++out_pos; + return result; + } + int read_out(uint8_t *bfr,int len); + int get_fd() { + return (access_type & io_UNBUFFERED) ? fd : fileno(fp); + } + void lock() { + if( (access_type & io_SINGLE_ACCESS) ) + io_lock.lock(); + if( !data ) data = new uint8_t[alloc]; + } + void unlock() { + if( (access_type & io_SINGLE_ACCESS) ) + io_lock.unlock(); + } + void start_reader(); + void stop_reader(); + int start_record(); + int stop_record(); + int write_align(int sz); + void write_record(int sz, int mask); + } *buffer; + + zmpeg3_t *src; + char path[STRLEN]; + int64_t current_byte; // Hypothetical position of file pointer + int64_t total_bytes; + int is_open; + + fs_t(zmpeg3_t *zsrc, const char *fpath, int access=io_UNBUFFERED+io_SINGLE_ACCESS); + fs_t(zmpeg3_t *zsrc, int fd, int access=io_UNBUFFERED+io_SINGLE_ACCESS); + fs_t(zmpeg3_t *zsrc, FILE *fp, int access=io_SINGLE_ACCESS); + fs_t(fs_t &fs); + ~fs_t(); + int open_file(); + void close_file(); + int errors() { return buffer ? buffer->errors() : 0; } + int get_fd() { return buffer ? buffer->get_fd() : -1; } + int read_data(uint8_t *bfr, int64_t len); + uint8_t next_char(); + uint8_t read_char(); + uint32_t read_uint16(); + uint32_t read_uint24(); + uint32_t read_uint32(); + uint64_t read_uint64(); + int seek(int64_t byte); + int seek_relative(int64_t bytes); + int64_t tell() { return current_byte; } + int64_t eof() { return current_byte >= total_bytes; } + int64_t bof() { return current_byte < 0; } + int64_t get_total_bytes(); + int64_t ztotal_bytes() { return total_bytes; } + void chk_next() { + if( ++current_byte >= buffer->file_tell() ) sync(); + } + void restart(); + int pause_reader(int v); + int access() { return !buffer ? 0 : buffer->access_type; } + void sequential() { buffer->access_type |= io_SEQUENTIAL; } + int start_record(int bsz); + int stop_record(); + void attach(fs_t *zfs); + void detach(); + void close_buffer(); + }; + + + // Bitstream + // next bit in forward direction + // next bit in reverse direction | + // v v + // ... | | | | | | | | |1|1|1|1|1|1| + // ^ ^ + // | bit_number = 1 + // bfr_size = 6 + + class bits_t { + public: + new_memset(0); + zmpeg3_t *src; + uint32_t bfr; // bfr = buffer for bits + int bit_number; // position of pointer in bfr + int bfr_size; // number of bits in bfr. Should always be a multiple of 8 + demuxer_t *demuxer; // Mpeg2 demuxer + uint8_t *input_ptr; // when input_ptr!=0, data is read from it instead of the demuxer. + + bits_t(zmpeg3_t *zsrc, demuxer_t *demux); + ~bits_t(); + int read_buffer(uint8_t *buffer, int byte); + void use_ptr(uint8_t *buffer); + int eos(uint8_t *ptr) { + return input_ptr - (bit_number+7)/8 >= ptr; + } + int eos(uint8_t *ptr,int bits) { + int n = bits - bit_number; + if( n <= 0 ) return 0; + return input_ptr + (n+7)/8 > ptr; + } + void use_demuxer(); + void start_reverse(); + void start_forward(); + int refill_ptr(); + int refill_noptr(); + int refill() { return input_ptr ? refill_ptr() : refill_noptr(); } + int refill_reverse(); + int open_title(int title); + int seek_byte(int64_t position); + void reset() { bfr_size = bit_number = 0; } + void reset(uint32_t v) { bfr = v; bfr_size = bit_number = 32; } + int get_bit_offset() { return bit_number & 7; } + void prev_byte_align() { bit_number = (bit_number+7) & ~7; } + void next_byte_align() { bit_number &= ~7; } + int bof() { return demuxer->zdata.bof() && demuxer->bof(); } + int eof() { return demuxer->zdata.eof() && demuxer->eof(); } + int error() { return demuxer->error(); } + int64_t tell(); + int next_code(uint32_t zcode); + int prev_code(uint32_t zcode); + int next_start_code(); + void pack_bits(uint32_t v, int n) { + bfr = (bfr << n) | v; + if( (bfr_size+=n) > (int)(8*sizeof(bfr)) ) + bfr_size = 8*sizeof(bfr); + bit_number += n; + } + void pack_8bits(uint32_t v) { pack_bits(v, 8); } + void fill_bits_ptr(int bits) { + while( bit_number < bits ) { pack_8bits(*input_ptr++); } + } + void fill_bits_noptr(int bits) { + while( bit_number < bits ) { pack_8bits(demuxer->read_char()); } + } + void fill_bits(int bits) { + return input_ptr ? fill_bits_ptr(bits) : fill_bits_noptr(bits); + } + uint32_t show_bits_noptr(int bits) { + if( bits <= 0 ) return 0; + fill_bits_noptr(bits); + return (bfr >> (bit_number-bits)) & (0xffffffff >> (32-bits)); + } + uint32_t show_bit_noptr(int bits) { return show_bits_noptr(1); } + uint32_t show_byte_noptr() { return show_bits_noptr(8); } + uint32_t show_bits24_noptr() { return show_bits_noptr(24); } + uint32_t show_bits32_noptr() { fill_bits_noptr(32); return bfr; } + int show_bits(int bits) { + if( bits <= 0 ) return 0; + fill_bits(bits); + return (bfr >> (bit_number-bits)) & (0xffffffff >> (32-bits)); + } + uint32_t get_bits_noptr(int bits) { + uint32_t result = show_bits_noptr(bits); + bit_number -= bits; + return result; + } + uint32_t get_bit_noptr() { return get_bits_noptr(1); } + int get_bits(int bits) { + uint32_t result = show_bits(bits); + bit_number -= bits; + return result; + } + uint32_t get_byte_noptr() { return get_bits_noptr(8); } + uint32_t get_bits24_noptr() { return get_bits_noptr(24); } + void fill_bits_reverse(int bits) { + int n = (bit_number & ~7); + if( n ) { bfr >>= n; bfr_size -= n; bit_number -= n; } + n = bit_number + bits; + while( bfr_size < n ) { + uint32_t prev_byte = input_ptr ? + *--input_ptr : demuxer->read_prev_char(); + bfr |= prev_byte << bfr_size; + bfr_size += 8; + } + } + int show_bits_reverse(int bits) { + fill_bits_reverse(bits); + return (bfr >> bit_number) & (0xffffffff >> (32 - bits)); + } + int get_bits_reverse(int bits) { + uint32_t result = show_bits_reverse(bits); + bit_number += bits; + return result; + } + }; + + + class index_t { + public: + new_memset(0); + float **index_data; // Buffer of frames for index. A frame is a high/low pair. + int index_allocated; // Number of frames allocated in each index channel. + int index_channels; // Number of index channels allocated + int index_size; // Number of high/low pairs in index channel + int index_zoom; // Downsampling of index buffers when constructing index + + index_t(); + ~index_t(); + }; + + + class bitfont_t { + public: + class bitchar_t; + static bitfont_t *fonts[]; + static int total_fonts; + static int font_refs; + static void init_fonts(); + static void destroy_fonts(); + class static_init_t { + public: + static_init_t(); + ~static_init_t(); + }; + class bitchar_t { + public: + uint16_t ch; + int16_t left, right; + int16_t ascent, decent; + uint8_t *bitmap; + } *chrs; + int16_t nch, idx, idy, imy; + }; + static bitfont_t *bitfont(int style,int pen_size,int italics,int size); + + class timecode_t { + public: + new_memset(0); + int hour; + int minute; + int second; + int frame; + + timecode_t() {} + ~timecode_t() {} + }; + + + class audio_t { + public: + new_memset(0); + class imdct_complex_t; + class imdct_al_table_t; + class audio_decoder_layer_t; + class audio_decoder_ac3_t; + class audio_decoder_pcm_t; + class ac3audblk_t; /*???*/ + + enum { + AC3_N = 512, + MAXFRAMESIZE = 4096, + MAXFRAMESAMPLEZ = MAXFRAMESAMPLES, + HDRCMPMASK = 0xfffffd00, + SBLIMIT = 32, + SSLIMIT = 18, + SCALE_BLOCK = 12, + MPEG3AUDIO_PADDING = 1024, + MAX_AC3_FRAMESIZE = 1920 * 2 + 512, + }; + + enum exponent_type { // Exponent strategy constants + exp_REUSE=0, + exp_D15=1, + exp_D25=2, + exp_D45=3, + }; + + enum delta_type { // Delta bit allocation constants + bit_REUSE=0, + bit_NEW=1, + bit_NONE=2, + bit_RESERVED=3, + }; + + enum mpg_md { // Values for mode + md_STEREO=0, + md_JOINT_STEREO=1, + md_DUAL_CHANNEL=2, + md_MONO=3, + }; + + enum { PCM_HEADERSIZE = 20, }; + + enum id3_state { + id3_IDLE=0, // No ID3 tag found + id3_HEADER=1, // Reading header + id3_SKIP=2, // Skipping ID3 tag + }; + + // IMDCT variables + class imdct_complex_t { + public: + float real; + float imag; + }; + + class imdct_al_table_t { + public: + short bits; + short d; + }; + + zmpeg3_t *src; + atrack_t *track; + + class l3_info_t { + public: + int scfsi; + uint32_t part2_3_length; + uint32_t big_values; + uint32_t scalefac_compress; + uint32_t block_type; + uint32_t mixed_block_flag; + uint32_t table_select[3]; + uint32_t subblock_gain[3]; + uint32_t maxband[3]; + uint32_t maxbandl; + uint32_t maxb; + uint32_t region1start; + uint32_t region2start; + uint32_t preflag; + uint32_t scalefac_scale; + uint32_t count1table_select; + float *full_gain[3]; + float *pow2gain; + }; + + class l3_sideinfo_t { + public: + uint32_t main_data_begin; + uint32_t private_bits; + class { public: l3_info_t gr[2]; } ch[2]; + }; + + class audio_decoder_layer_t { + static int tabsel_123[2][3][16]; + static long freqs[9]; + static float decwin[512 + 32]; + static float cos64[16], cos32[8], cos16[4], cos8[2], cos4[1]; + static float *pnts[5]; + static int grp_3tab[32 * 3]; /* used: 27 */ + static int grp_5tab[128 * 3]; /* used: 125 */ + static int grp_9tab[1024 * 3]; /* used: 729 */ + static float muls[27][64]; /* also used by layer 1 */ + static float gainpow2[256 + 118 + 4]; + static long intwinbase[257]; + static float ispow[8207]; + static float aa_ca[8], aa_cs[8]; + static float win[4][36]; + static float win1[4][36]; + static float COS1[12][6]; + static float COS9[9]; + static float COS6_1, COS6_2; + static float tfcos36[9]; + static float tfcos12[3]; + static float cos9[3], cos18[3]; + static float tan1_1[16], tan2_1[16], tan1_2[16], tan2_2[16]; + static float pow1_1[2][16], pow2_1[2][16]; + static float pow1_2[2][16], pow2_2[2][16]; + static int longLimit[9][23]; + static int shortLimit[9][14]; + static class bandInfoStruct { + public: + int longIdx[23], longDiff[22]; + int shortIdx[14], shortDiff[13]; + } bandInfo[9]; + static int mapbuf0[9][152]; + static int mapbuf1[9][156]; + static int mapbuf2[9][44]; + static int *map[9][3]; + static int *mapend[9][3]; + static uint32_t n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ + static uint32_t i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ + + static short tab0 [ 1], tab1 [ 7], tab2 [17], tab3[ 17]; + static short tab5 [ 31], tab6 [ 31], tab7 [71], tab8[ 71]; + static short tab9 [ 71], tab10[127], tab11[127], tab12[127]; + static short tab13[511], tab15[511], tab16[511], tab24[511]; + static short tab_c0[31], tab_c1[31]; + static class huffman_t { + public: + unsigned int linbits; + short *table; + } ht[32], htc[2]; + + static int dct64_1(float *out0,float *out1,float *b1,float *b2, + float *samples); + static int dct64(float *a,float *b,float *c); + static int dct36(float *inbuf,float *o1,float *o2,float *wintab, + float *tsbuf); + static int dct12(float *in,float *rawout1,float *rawout2,float *wi, + float *ts); + + int get_scale_factors_1(int *scf,l3_info_t *l3_info,int ch,int gr); + int get_scale_factors_2(int *scf,l3_info_t *l3_info,int i_stereo); + int dequantize_sample(float xr[SBLIMIT][SSLIMIT],int *scf, + l3_info_t *l3_info,int sfreq,int part2bits); + int get_side_info(l3_sideinfo_t *si,int channels,int ms_stereo, + long sfreq,int single,int lsf); + int hybrid(float fsIn[SBLIMIT][SSLIMIT], + float tsOut[SSLIMIT][SBLIMIT],int ch,l3_info_t *l3_info); + int antialias(float xr[SBLIMIT][SSLIMIT],l3_info_t *l3_info); + int calc_i_stereo(float xr_buf[2][SBLIMIT][SSLIMIT],int *scalefac, + l3_info_t *l3_info,int sfreq,int ms_stereo,int lsf); + int synth_stereo(float *bandPtr,int channel,float *out, int *pnt); + int init_audio(zmpeg3_t *zsrc, atrack_t *ztrack, int zformat); + int synths_reset(); + int select_table(); + int step_one(uint8_t *bit_alloc, int *scale); + int step_two(uint8_t *bit_alloc, float fraction[2][4][SBLIMIT], + int *scale, int x1); + public: + new_memset(0); + bits_t *stream; + // Layer 3 + uint8_t *bsbuf, *prev_bsbuf; + uint8_t bsspace[2][MAXFRAMESIZE + 512]; // MAXFRAMESIZE + int bsnum; + // For mp3 current framesize without header. For AC3 current framesize with header. + long framesize; + long prev_framesize, past_framesize; + int channels; + int samplerate; + int single; + int sampling_frequency_code; + int error_protection; + int mode; + int mode_ext; + int lsf; + long ssize; + int mpeg35; + int padding; + int layer; + int extension; + int copyright; + int original; + int emphasis; + int bitrate; + // Static variable in synthesizer + int bo; + // Ignore first frame after a seek + int first_frame; + float synth_stereo_buffs[2][2][0x110]; + float synth_mono_buff[64]; + float mp3_block[2][2][SBLIMIT * SSLIMIT]; + int mp3_blc[2]; + + // State of ID3 parsing + int id3_state; + int id3_current_byte; + int id3_size; + // Layer 2 + int bitrate_index; + imdct_al_table_t *alloc; + int jsbound; + int II_sblimit; + uint8_t layer2_scfsi_buf[64]; + + void layer_reset(); + static int layer_check(uint8_t *data); + static int id3_check(uint8_t *data); + int layer3_header(uint8_t *data); + audio_decoder_layer_t(); + ~audio_decoder_layer_t(); + int do_layer2(uint8_t *zframe,int zframe_size,float **zoutput,int render); + int do_layer3(uint8_t *zframe,int zframe_size,float **zoutput,int render); + int init_layer2(); + int init_layer3(); + int init_decode_tables(); + } *layer_decoder; + + class audio_decoder_ac3_t { + public: + new_memset(0); + static int ac3_samplerates[3]; + + bits_t *stream; + int samplerate; + int bitrate; + int flags; + int channels; + a52_state_t *state; + sample_t *output; + int framesize; + static int ac3_check(uint8_t *data); + int ac3_header(uint8_t *data); + int do_ac3(uint8_t *zframe, int zframe_size, float **zoutput, int render); + audio_decoder_ac3_t(); + ~audio_decoder_ac3_t(); + } *ac3_decoder; + + class audio_decoder_pcm_t { + public: + new_memset(0); + int samplerate; + int bits; + int channels; + int framesize; + int pcm_header(uint8_t *data); + int do_pcm(uint8_t *zframe, int zframe_size, float **zoutput, int render); + audio_decoder_pcm_t() {} + ~audio_decoder_pcm_t() {} + } *pcm_decoder; + + int channels; // channels from read_header + int samplerate; // samplerate from read_header + int framenum; // Number of current frame being decoded + int framesize; // Size of frame including header + int64_t start_byte; // First byte of audio data in the file + int output_channels; // number of defined output buffers + float **output; // Output from synthesizer in linear floats + int output_size; // Number of pcm samples in the buffer + int output_allocated; // Allocated number of samples in output + int64_t output_position; // Sample position in file of start of output buffer + int64_t sample_seek; // Perform a seek to the sample + int64_t byte_seek; // Perform a seek to the absolute byte + // +/- number of samples of difference between audio and video + int seek_correction; + // Buffer containing current packet + uint8_t packet_buffer[MAXFRAMESIZE]; + // Position in packet buffer of next byte to read + int packet_position; + + audio_t() {} + int init_audio(zmpeg3_t *zsrc, atrack_t *ztrack, int zformat); + ~audio_t(); + + int rewind_audio(); + int read_header(); + void update_channels(); + int audio_pts_padding(); + int audio_pts_skipping(int samples); + void update_audio_history(); + int read_frame(int render); + int get_length(); + int seek(); + int seek_byte(int64_t byte); + int seek_sample(long sample); + int read_raw(uint8_t *output,long *size,long max_size); + void shift_audio(int64_t diff); + int decode_audio(void *output_v,int atyp,int channel,int len); + int64_t audio_position() { return output_position + output_size; } + }; + + class VLCtab_t { + public: + int8_t val, len; + }; + + class DCTtab_t { + public: + int8_t run, level; + int16_t len; + }; + + class slice_buffer_t { + static VLCtab_t DClumtab0[32]; + static VLCtab_t DClumtab1[16]; + static VLCtab_t DCchromtab0[32]; + static VLCtab_t DCchromtab1[32]; + + public: + slice_buffer_t *next; // avail list link + uint8_t *data; // Buffer for holding the slice data + video_t *video; // decoder + int buffer_size; // Size of buffer + int buffer_allocation; // Space allocated for buffer + int buffer_position; // Position in buffer + uint32_t bits; + int bits_size; + + int eob() { return buffer_position >= buffer_size; } + uint32_t get_data_byte() { return data[buffer_position++]; } + void fill_bits(int nbits) { + while( bits_size < nbits ) { + bits <<= 8; + if( !eob() ) bits |= get_data_byte(); + bits_size += 8; + } + } + void flush_bits(int nbits) { fill_bits(nbits); bits_size -= nbits; } + void flush_bit() { flush_bits(1); } + uint32_t show_bits(int nbits) { + fill_bits(nbits); + return (bits >> (bits_size-nbits)) & (0xffffffff >> (32-nbits)); + } + uint32_t get_bits(int nbits) { + uint32_t result = show_bits(nbits); + bits_size -= nbits; + return result; + } + uint32_t get_bit() { return get_bits(1); } + int get_dc_lum(); + int get_dc_chrom(); + uint8_t *expand_buffer(int bfrsz); + void fill_buffer(bits_t *vstream); + int ext_bit_info(); + + slice_buffer_t(); + ~slice_buffer_t(); + }; + + + class video_t { + static uint8_t zig_zag_scan_nommx[64]; // zig-zag scan + static uint8_t alternate_scan_nommx[64]; // alternate scan + // default intra quantization matrix + static uint8_t default_intra_quantizer_matrix[64]; + // Frame rate table must agree with the one in the encoder + static double frame_rate_table[16]; + + inline void recon_comp(uint8_t *s, uint8_t *d, + int lx, int lx2, int h, int type); + void recon(uint8_t *src[], int sfield, + uint8_t *dst[], int dfield, int lx, int lx2, + int w, int h, int x, int y, int dx, int dy, int addflag); + int delete_decoder(); + void init_scantables(); + int read_frame_backend(int skip_bframes); + int *get_scaletable(int input_w, int output_w); + int get_gop_header(); + long gop_to_frame(timecode_t *gop_timecode); + int seek(); + + public: + new_memset(0); + class cc_t; + + enum chroma_format { + cfmt_420=1, + cfmt_422=2, + cfmt_444=3, + }; + + enum ext_start_code { + ext_id_SEQ=1, + ext_id_DISP=2, + ext_id_QUANT=3, + ext_id_SEQSCAL=5, + ext_id_PANSCAN=7, + ext_id_CODING=8, + ext_id_SPATSCAL=9, + ext_id_TEMPSCAL=10, + }; + + enum picture_type { + pic_type_I=1, + pic_type_P=2, + pic_type_B=3, + pic_type_D=4, + }; + + enum picture_structure { + pics_TOP_FIELD=1, + pics_BOTTOM_FIELD=2, + pics_FRAME_PICTURE=3, + }; + + slice_buffer_t *slice_buffers, *avail_slice_buffers; + int total_slice_buffers; + void allocate_slice_buffers(); + void delete_slice_buffers(); + void reallocate_slice_buffers(); + zlock_t slice_lock, slice_wait, slice_active; + int slice_wait_locked, slice_active_locked; + + zmpeg3_t *src; + vtrack_t *track; + + // ================================= Seeking variables ========================= + bits_t *vstream; + int decoder_initted; + uint8_t **output_rows; // Output frame buffer supplied by user + int in_x, in_y, in_w, in_h, out_w, out_h; // Output dimensions + int row_span; + int *x_table, *y_table; // Location of every output pixel in the input + int color_model; + int want_yvu; // Want to return a YUV frame + char *y_output, *u_output, *v_output; // Output pointers for a YUV frame + + int blockreadsize; + int maxframe; // Max value of frame num to read + int64_t byte_seek; // Perform absolute byte seek before the next frame is read + int frame_seek; // Perform a frame seek before the next frame is read + int framenum; // Number of the next frame to be decoded + int last_number; // Last framenum rendered + int ref_frames; // ref_frames since last seek + int found_seqhdr; + int bitrate; + timecode_t gop_timecode; // Timecode for the last GOP header read. + int has_gops; // Some streams have no GOPs so try sequence start codes instead + + class cc_t { // close captioning (atsc only) + video_t *video; + uint8_t data[3][128]; // reorder buffers + int frs_history, font_size; + void decode(int idx); + public: + class svc_t; + + enum { + MX_SVC = 64, MX_WIN=8,MX_CX=48,MX_CY=16, + /* frame struct history */ + frs_tf1 = 0x01, /* top field in data[1] */ + frs_bf2 = 0x02, /* bottom field in data[2] */ + frs_frm = 0x04, /* frame in data[1] */ + frs_prc = 0x08, /* frame processed */ + st_unmap=-1, st_hidden=0, st_visible=1, /* state */ + dir_rt=0, dir_lt=1, dir_up=2, dir_dn=3, /* print/scroll/effect dir */ + jfy_left=0, jfy_right=1, jfy_center=2, jfy_full=3, /* justify */ + eft_snap = 0, eft_fade = 1, eft_wipe = 2, /* effect */ + oty_solid=0, oty_flash=1, oty_translucent=2, + oty_transparent=3, bdr_width=5, /* opacity/border width */ + edg_none=0, edg_raised=1, edg_depressed=2, edg_uniform=3, + edg_shadow_left=4, edg_shadow_right=5, /* edge type */ + psz_small=0, psz_standard=1, psz_large=2, /* pen size */ + fst_default=0, fst_mono_serif=1, fst_prop_serif=2, + fst_mono_sans=3, fst_prop_sans=4, fst_casual=5, + fst_cursive=6, fst_small_caps=7, /* font style */ + fsz_small=0, fsz_normal=1, fsz_large=2, /* font size */ + tag_dialog=0, tag_source_id=1, tag_device=2, + tag_dialog_2=3, tag_voiceover=4, tag_audible_transl=5, + tag_subtitle_transl=6, tag_voice_descr=7, tag_lyrics=8, + tag_effect_descr=9, tag_score_descr=10, tag_expletive=11, + tag_not_displayable=15, /* text tag */ + ofs_subscript=0, ofs_normal=1, ofs_superscript=2, /* offset */ + }; + /* color RGB 2:2:2 (lsb = B). */ + class svc_t { + cc_t *cc; + int sid, ctrk, size; + uint8_t *bp, *ep; + uint8_t data[128]; + public: + class chr_t { + public: + uint16_t glyph; + uint8_t fg_opacity : 2; + uint8_t fg_color : 6; + uint8_t bg_opacity : 2; + uint8_t bg_color : 6; + uint8_t pen_size : 2; + uint8_t edge_color : 6; + uint8_t italics : 1; + uint8_t edge_type : 3; + uint8_t underline : 1; + uint8_t font_style : 3; + uint8_t font_size : 2; + uint8_t offset : 2; + uint8_t text_tag : 4; + uint8_t rsvd2; + } *bfrs; + chr_t *get_bfr(); + void bfr_put(chr_t *&bfr); + + class win_t; + class win_t { + public: + class chr_attr_t; + int8_t id, st, pdir, sdir; + uint8_t cx, cy, cw, ch; /* pen/dim in bytes */ + int ax, ay, x, y, bw; /* anchor/pen/border in pixels */ + uint32_t fg_yuva, bg_yuva, edge_yuva; /* pen color */ + uint32_t fill_yuva, border_yuva; /* window color */ + int start_frame, end_frame; + svc_t *svc; + subtitle_t *subtitle; + uint8_t anchor_point, anchor_horizontal, anchor_vertical; + uint8_t anchor_relative, row_lock, col_lock, dirty; + uint8_t priority, window_style, pen_style; + /* pen style properties */ + uint8_t pen_size, font_style, offset, italics, underline; + uint8_t fg_color, fg_opacity, bg_color, bg_opacity; + uint8_t text_tag, edge_color, edge_type, scale; + /* window style properties */ + uint8_t justify, wordwrap, fill_opacity, fill_color; + uint8_t display_effect, effect_speed, effect_direction; + uint8_t border_type, border_color, border_width; + chr_t *bfr; + + win_t(); + ~win_t(); + void reset(int i,svc_t *svc); + int BS(); int FF(); int CR(); int HCR(); + int init(int ncw, int nch); + int resize(int ncw, int nch); + static int is_breakable(int b); + int wrap(); + int ovfl(); + int store(int ch); + void set_window_style(int i); + void set_pen_style(int i); + void default_window(); + void print_buffer(); + void hbar(int x, int y, int ww, int hh, int lm, int rm, int clr); + void vbar(int x, int y, int ww, int hh, int tm, int bm, int clr); + void border(int ilt, int olt, int irt, int ort, + int iup, int oup, int idn, int odn); + void put_chr(chr_t *chr); + static bitfont_t *chr_font(chr_t *bp, int scale); + void render(); + void output_text(); + void set_state(int8_t st); + } win[MX_WIN], *curw; + svc_t(cc_t *cc); + ~svc_t(); + int id() { return sid; } + int trk() { return ctrk; } + void append(uint8_t *bp, int len); + void decode(); + int render(); + void reset(int sid,cc_t *cc); + int CWx(int id); int DFz(int id); + int DFx(int id); int RSVD(); int ETX(); + int BS(); int FF(); int CR(); int HCR(); + int RST(); int DLC(); int DLW(); int DLY(); + int CLW(); int DSW(); int HDW(); int TGW(); + int SPA(); int SPC(); int SPL(); int SWA(); + int command(int cmd); + static uint32_t pen_yuva(int color, int opacity); + } svc; + + cc_t(video_t *video); + ~cc_t(); + void reset(); + void get_atsc_data(bits_t *v); + void decode(); + void reorder(); + zcc_text_cb text_cb; + } *cc; + cc_t *get_cc(); + int subtitle_track; // Subtitle track to composite if >= 0 + int show_subtitle(int strk); + + // These are only available from elementary streams. + int frames_per_gop; // Frames per GOP after the first GOP. + int first_gop_frames; // Frames in the first GOP. + int first_frame; // Number of first frame stored in timecode + int last_frame; // Last frame in file + + // ================================= Compression variables ===================== + // Malloced frame buffers. 2 refframes are swapped in and out. + // while only 1 auxframe is used. + uint8_t *yuv_buffer[5]; // Make YVU buffers contiguous for all frames + uint8_t *oldrefframe[3], *refframe[3], *auxframe[3]; + uint8_t *llframe0[3], *llframe1[3]; + uint8_t *zigzag_scan_table; + uint8_t *alternate_scan_table; + // Source for the next frame presentation + uint8_t *output_src[3]; + // Pointers to frame buffers. + uint8_t *newframe[3]; + uint8_t *tdat; + int horizontal_size, vertical_size, mb_width, mb_height; + int coded_picture_width, coded_picture_height; + int chroma_format, chrom_width, chrom_height, blk_cnt; + int8_t pict_type, pict_struct, field_sequence, intravlc; + int8_t forw_r_size, back_r_size, full_forw, full_back; + int8_t prog_seq, prog_frame, repeatfirst, secondfield; + int8_t h_forw_r_size, v_forw_r_size, h_back_r_size, v_back_r_size; + int8_t dc_prec, topfirst, frame_pred_dct, conceal_mv; + union { + struct { int8_t got_top, got_bottom, repeat_fields, current_field; }; + int32_t repeat_data; + }; + int skip_bframes; + int frame_time, seek_time; + int stwc_table_index, llw, llh, hm, hn, vm, vn; + int lltempref, llx0, lly0, llprog_frame, llfieldsel; + int matrix_coefficients; + int framerate_code; + double frame_rate; + int *cr_to_r, *crb_to_g, *cb_to_b; + int intra_quantizer_matrix[64], non_intra_quantizer_matrix[64]; + int chroma_intra_quantizer_matrix[64], chroma_non_intra_quantizer_matrix[64]; + int mpeg2; + int skim; // skip reconstruction/motion + int thumb, ithumb; // thumbnail scan/ thumbnail frame ready + int qscale_type, altscan; // picture coding extension + int pict_scal; // picture spatial scalable extension + int scalable_mode; // sequence scalable extension + + // Subtitling frame + uint8_t *subtitle_frame[3]; + + video_t(zmpeg3_t *zsrc, vtrack_t *ztrack); + ~video_t(); + void init_video(); + int seek_video() { return seek(); } + void reset_subtitles(); + int eof(); + + int set_cpus(int cpus); + int set_mmx(int use_mmx); + void cache_frame(); + int drop_frames(long frames, int cache_it); + int colormodel(); + int read_frame(uint8_t **output_rows, + int in_x, int in_y, int in_w, int in_h, + int out_w, int out_h, int color_model); + int read_yuvframe(char *y_output, char *u_output, char *v_output, + int in_x, int in_y, int in_w, int in_h); + int read_yuvframe_ptr(char **y_output, char **u_output, char **v_output); + int read_raw(uint8_t *output, long *size, long max_size); + int seek_frame(long frame); + int seek_byte(int64_t byte); + int rewind_video(int preload=1); + int previous_frame(); + int init_decoder(); + void new_output(); + int reconstruct( int bx, int by, int mb_type, int motion_type, + int PMV[2][2][2], int mv_field_sel[2][2], + int dmvector[2], int stwtype); + void dump(); + slice_buffer_t *get_slice_buffer(); + void put_slice_buffer(slice_buffer_t* buffer); + int get_macroblocks(); + int display_second_field(); + int video_pts_padding(); + int video_pts_skipping(); + int read_picture(); + int get_picture(); + int get_seq_hdr(); + int sequence_extension(); + int sequence_display_extension(); + int quant_matrix_extension(); + int sequence_scalable_extension(); + int picture_display_extension(); + int picture_coding_extension(); + int picture_spatial_scalable_extension(); + int picture_temporal_scalable_extension(); + int ext_user_data(); + int get_picture_hdr(); + int find_header(); + int get_header(); + void overlay_subtitle(subtitle_t *subtitle); + void decode_subtitle(); + int init_output(); + int dither_frame(uint8_t *yy, uint8_t *uu, uint8_t *vv,uint8_t **output_rows); + int dither_frame444(uint8_t *yy, uint8_t *uu, uint8_t *vv); + int dithertop(uint8_t *yy, uint8_t *uu, uint8_t *vv); + int dithertop444(uint8_t *yy, uint8_t *uu, uint8_t *vv); + int ditherbot(uint8_t *yy, uint8_t *uu, uint8_t *vv); + int ditherbot444(uint8_t *yy, uint8_t *uu, uint8_t *vv); + int present_frame(uint8_t *yy, uint8_t *uu, uint8_t *vv); + void calc_dmv(int DMV[][2],int *dmvector,int mvx,int mvy); + int is_refframe() { return pict_type == pic_type_B ? 0 : + pict_struct == pics_FRAME_PICTURE ? 1 : secondfield; + } + }; + + + class slice_decoder_t { + public: + static VLCtab_t PMBtab0[8]; + static VLCtab_t PMBtab1[8]; + static VLCtab_t BMBtab0[16]; + static VLCtab_t BMBtab1[8]; + static VLCtab_t spIMBtab[16]; + static VLCtab_t spPMBtab0[16]; + static VLCtab_t spPMBtab1[16]; + static VLCtab_t spBMBtab0[14]; + static VLCtab_t spBMBtab1[12]; + static VLCtab_t spBMBtab2[8]; + static VLCtab_t SNRMBtab[8]; + static VLCtab_t MVtab0[8]; + static VLCtab_t MVtab1[8]; + static VLCtab_t MVtab2[12]; + static VLCtab_t CBPtab0[32]; + static VLCtab_t CBPtab1[64]; + static VLCtab_t CBPtab2[8]; + static VLCtab_t MBAtab1[16]; + static VLCtab_t MBAtab2[104]; + + static DCTtab_t DCTtabfirst[12]; + static DCTtab_t DCTtabnext[12]; + static DCTtab_t DCTtab0[60]; + static DCTtab_t DCTtab0a[252]; + static DCTtab_t DCTtab1[8]; + static DCTtab_t DCTtab1a[8]; + static DCTtab_t DCTtab2[16]; + static DCTtab_t DCTtab3[16]; + static DCTtab_t DCTtab4[16]; + static DCTtab_t DCTtab5[16]; + static DCTtab_t DCTtab6[16]; + + // non-linear quantization coefficient table + static uint8_t non_linear_mquant_table[32]; + + enum macroblock_type { + mb_INTRA=1, + mb_PATTERN=2, + mb_BACKWARD=4, + mb_FORWARD=8, + mb_QUANT=16, + mb_WEIGHT=32, + mb_CLASS4=64, + }; + + enum motion_type { + mc_FIELD=1, + mc_FRAME=2, + mc_16X8=2, + mc_DMV=3, + }; + + enum mv_format { + mv_FIELD=0, + mv_FRAME=1, + }; + + enum scalable_mode { + sc_NONE=0, + sc_DP=1, + sc_SPAT=2, + sc_SNR=3, + sc_TEMP=4, + }; + + slice_decoder_t *next; + zmpeg3_t *src; + video_t *video; + pthread_t owner; // for debugging + slice_buffer_t *slice_buffer; + int fault; + int done; + int quant_scale; + int pri_brk; // slice/macroblock + short block[12][64]; + int sparse[12]; + pthread_t tid; // ID of thread + zlock_t input_lock; + + int val, sign, idx; + int get_cbp(); + int clear_block(int comp, int size); + static uint16_t *DCTlutab[3]; + static uint16_t lu_pack(DCTtab_t *lp) { + int run = lp->run>=64 ? lp->run-32 : lp->run; + return run | ((lp->len-1)<<6) | (lp->level<<10); + } + static int lu_run(uint16_t lu) { return lu & 0x3f; } + static int lu_level(uint16_t lu) { return lu >> 10; } + static int lu_len(uint16_t lu) { return ((lu>>6) & 0x0f) + 1; } + static void init_lut(uint16_t *&lutbl, DCTtab_t *tabn, DCTtab_t *tab0, DCTtab_t *tab1); + static void init_tables(); + int get_coef(uint16_t *lut); + int get_mpg2_coef(uint16_t *lut); + void get_intra_block(int comp, int dc_dct_pred[]); + void get_mpg2_intra_block(int comp, int dc_dct_pred[]); + void get_inter_block(int comp); + void get_mpg2_inter_block(int comp); + int get_slice_hdr(); + int decode_slice(); + void slice_loop(); + static void *the_slice_loop(void *the_slice_decoder); + int get_mv(); + int get_dmv(); + void motion_vector(int *PMV, int *dmvector, int h_r_size, int v_r_size, + int dmv, int mvscale, int full_pel_vector); + int motion_vectors(int PMV[2][2][2], int dmvector[2], int mv_field_sel[2][2], + int s, int mv_count, int mv_format, int h_r_size, int v_r_size, + int dmv, int mvscale); + int get_macroblock_address(); + inline int getsp_imb_type(); + inline int getsp_pmb_type(); + inline int getsp_bmb_type(); + inline int get_imb_type(); + inline int get_pmb_type(); + inline int get_bmb_type(); + inline int get_dmb_type(); + inline int get_snrmb_type(); + int get_mb_type(); + int macroblock_modes(int *pmb_type,int *pstwtype, int *pstwclass, + int *pmotion_type,int *pmv_count,int *pmv_format,int *pdmv, + int *pmvscale,int *pdct_type); + int add_block(int comp,int bx,int by,int dct_type,int addflag); + static void idct_conversion(short* block); + int get_active_slice_buffer(); + + slice_decoder_t(); + ~slice_decoder_t(); + } *slice_decoders, *avail_slice_decoders; + + int total_slice_decoders; + slice_buffer_t *active_slice_buffers; + zlock_t decoder_lock, decoder_active; + int decoder_active_locked; + void allocate_slice_decoders(); + void delete_slice_decoders(); + void reallocate_slice_decoders(); + void decode_slice(slice_buffer_t* buffer); + + + class subtitle_t { + public: + new_memset(0); + uint8_t *data; // Raw data of subtitle + int data_allocated, data_used; + int id; // Number of stream starting at 0x20 + int done; // -1 avail, 0 read in, 1 decode + int active; // 1 subtitle is contructed, -1 subtitle is close caption + int draw; // -1 never draw, 0 draw based on frame time, 1 always draw + int64_t offset; // Program offset of start of subtitle + int force; // 1 Force display, -1 force delete + // image in YUV444 + int w, h, sz; + uint8_t *image_y, *image_u, *image_v, *image_a; + int x1, x2, y1, y2; + int start_time; // Time after detection of subtitle to display it in msec + int stop_time; // Time after detection of subtitle to hide it in msec + int palette[4]; // Indexes in the main palette + int alpha[4]; + int start_frame, stop_frame; // framenum start/stop drawing + int frame_time; // presentation frame_time at creation + + subtitle_t(); + subtitle_t(int nid, int ww, int hh); + ~subtitle_t(); + + void realloc_data(int count); + int decompress_subtitle(zmpeg3_t *zsrc); + void set_image_size(int isz); + void set_image_size(int ww, int hh); + int decode(video_t *video); + }; + + class demuxer_t { + friend class bits_t; + + uint8_t packet_next_char() { return raw_data[raw_offset]; } + uint8_t packet_read_char() { return raw_data[raw_offset++]; } + uint32_t packet_read_int16() { + uint32_t a = raw_data[raw_offset++]; + uint32_t b = raw_data[raw_offset++]; + return (a << 8) | b; + } + uint32_t packet_next_int24() { + uint32_t a = raw_data[raw_offset+0]; + uint32_t b = raw_data[raw_offset+1]; + uint32_t c = raw_data[raw_offset+2]; + return (a << 16) | (b << 8) | c; + } + uint32_t packet_read_int24() { + uint32_t a = raw_data[raw_offset++]; + uint32_t b = raw_data[raw_offset++]; + uint32_t c = raw_data[raw_offset++]; + return (a << 16) | (b << 8) | c; + } + uint32_t packet_read_int32() { + uint32_t a = raw_data[raw_offset++]; + uint32_t b = raw_data[raw_offset++]; + uint32_t c = raw_data[raw_offset++]; + uint32_t d = raw_data[raw_offset++]; + return (a << 24) | (b << 16) | (c << 8) | d; + } + void packet_skip(int length) { raw_offset += length; } + int get_adaptation_field(); + int get_program_association_table(); + int get_transport_payload(int is_audio, int is_video); + int get_pes_packet_header(uint64_t *pts, uint64_t *dts); + int get_unknown_data(); + int get_transport_pes_packet(); + int get_pes_packet(); + int get_payload(); + int read_transport(); + int get_system_header(); + uint64_t get_timestamp(); + int get_pack_header(); + int get_program_payload(int bytes, int is_audio, int is_video); + int handle_scrambling(int decryption_offset); + void del_subtitle(int idx); + subtitle_t* get_subtitle(int id,int64_t offset); + void handle_subtitle(zmpeg3_t *src, int stream_id, int bytes); + int handle_pcm(int bytes); + int get_program_pes_packet(uint32_t header); + int previous_code(uint32_t zcode); + + public: + new_memset(0); + class zstream_t; + class title_t; + class nav_t { + public: +#include "nav.h" + new_memset(0); + } *nav; + + zmpeg3_t* src; + uint8_t *raw_data; // One unparsed packet. + int raw_offset; // Offset in raw_data of read pointer + int raw_size; // Amount loaded in last raw_data + + // Elementary stream data when only one stream is to be read. + // Erased in every call to read a packet. + class zstream_t { + public: + new_memset(0); + uint8_t *buffer; + int allocated; // Allocation of data_buffer + int size; // Position in data_buffer of write pointer + int position; // Position in data_buffer of read pointer + int start; // Start of the next pes packet + int length() { return size - position; } + bool eof() { return position >= size; } + bool bof() { return position == 0; } + } zdata; + // Elementary stream data when all streams are to be read. There is no + // read pointer since data is expected to be copied directly to a track. + // Some packets contain audio and video. Further division into + // stream ID may be needed. + zstream_t zaudio; + zstream_t zvideo; + + subtitle_t *subtitles[MAX_SUBTITLES]; + int total_subtitles; + + // What type of data to read, which track is accessing + atrack_t *do_audio; + vtrack_t *do_video; + int read_all; + // Direction of reads + int reverse; + // Set to 1 when eof or attempt to read before beginning + int error_flag; + int discontinuity; + // Temp variables for returning + uint8_t next_char; + // Info for mpeg3cat + int64_t last_packet_start; + int64_t last_packet_end; + int64_t last_packet_decryption; + + // Table of contents + class title_t { // Titles + void extend_cell_table(); + public: + new_memset(0); + class cell_t; + + zmpeg3_t *src; + fs_t *fs; + int64_t total_bytes; // Total bytes in title file. + int64_t start_byte; // Absolute starting byte of the title in the stream + int64_t end_byte; // Absolute ending byte of the title in the stream + 1 + // May get rid of time values and rename to a cell offset table. + // May also get rid of end byte. + + class cell_t { + public: + new_memset(0); + int64_t title_start; // Starting byte of cell in the title (start_byte) + int64_t title_end; // Ending byte of cell in the title (end_byte) + int64_t program_start; // Starting byte of the cell in the program + int64_t program_end; // Ending byte of the cell in the program + double cell_time; // play time at end of cell, -1 if unknown + int cell_no; // cell in original cell table + int discontinuity; + + cell_t() {} + ~cell_t() {} + } *cell_table; // Timecode table + int cell_table_size; // Number of entries + int cell_table_allocation; // Number of available slots + + title_t(zmpeg3_t *zsrc, char *fpath); + title_t(zmpeg3_t *zsrc); + ~title_t(); + title_t(title_t &title); + void new_cell(int cell_no, + int64_t title_start, int64_t title_end, + int64_t program_start, int64_t program_end, + int discontinuity); + void new_cell(int64_t byte_end) { // default cell + new_cell(0, 0, byte_end, 0, byte_end, 0); + } + int dump_title(); + int print_cells(FILE *output); + } *titles[MAX_STREAMZ]; + int total_titles; + int current_title; // Title currently being used + + // Tables of every stream ID encountered + int8_t astream_table[MAX_STREAMZ]; // afmt index + int8_t vstream_table[MAX_STREAMZ]; // 1 if video + int8_t sstream_table[MAX_STREAMZ]; // 1 if subtitle + + // Cell in the current title currently used + int title_cell; + int64_t nav_cell_next_vobu; + int64_t nav_cell_end_byte; + + // Byte position in current program. + int64_t program_byte; + // Total bytes in all titles + int64_t total_bytes; + // The end of the current stream in the current program + int64_t stream_end; + + int transport_error_indicator; + int payload_unit_start_indicator; + int pid; // PID of last packet + int stream_id; // Stream ID of last packet + int custom_id; // Custom ID of last packet + int transport_scrambling_control; + int adaptation_field_control; + int continuity_counter; + int is_padding; + int pid_table[PIDMAX]; + int continuity_counters[PIDMAX]; + int total_pids; + int adaptation_fields; + double time; // Time in seconds + uint32_t last_code; + int audio_pid; + int video_pid; + int subtitle_pid; + int got_audio; + int got_video; + // if subtitle object was created in last packet + int got_subtitle; + // When only one stream is to be read, these store the stream IDs + // Audio stream ID being decoded. -1 = select first ID in stream + int astream; + // Video stream ID being decoded. -1 = select first ID in stream + int vstream; + // Multiplexed streams have the audio type + // Format of the audio derived from multiplexing codes + int aformat; + int program_association_tables; + int table_id; + int section_length; + int transport_stream_id; + int pes_packets; + double pes_audio_time; // Presentation Time stamps + double pes_video_time; + int pes_audio_pid; // custom_id of timestamp + int pes_video_pid; + // Cause the stream parameters to be dumped in human readable format + int dump; + + demuxer_t(zmpeg3_t *zsrc,atrack_t *do_aud,vtrack_t *do_vid,int cust_id); + ~demuxer_t(); + + int create_title(int full_scan=0); + int64_t tell_byte() { return program_byte; } + int64_t absolute_position() { + return titles[current_title]->fs->tell() + titles[current_title]->start_byte; + } + bool eof(); + bool bof(); + bool error() { return error_flag; } + int64_t movie_size(); + double get_time() { return time; } + int get_cell(int no, title_t::cell_t *&v); + void start_reverse(); + void start_forward(); + int seek_byte(int64_t byte); + double scan_pts(); + int goto_pts(double pts); + int seek_phys(); + int read_program(); + int64_t prog2abs_fwd(int64_t byte, int64_t *nbyte, int *ntitle, int *ncell); + int64_t prog2abs_rev(int64_t byte, int64_t *nbyte, int *ntitle, int *ncell); + int64_t program_to_absolute(int64_t byte, int64_t *nbyte=0, int *ntitle=0, int *ncell=0); + int64_t absolute_to_program(int64_t byte); + int64_t title_bytes(); + void append_data(uint8_t *data, int bytes); + void shift_data(); + int open_title(int title_number); + int copy_titles(demuxer_t *dst); + void end_title(int64_t end_byte); + int next_code(uint32_t zcode); + int prev_code(uint32_t zcode); + uint8_t read_char_packet(); + uint8_t read_prev_char_packet(); + uint8_t read_char() { + if( zunlikely(zdata.eof()) ) return read_char_packet(); + return zdata.buffer[zdata.position++]; + } + uint8_t read_prev_char(); + int read_data(uint8_t *output,int size); + int read_next_packet(); + int read_prev_packet(); + void skip_video_frame(); + int64_t next_cell(); + int64_t playinfo_next_cell(); + double video_pts() { double pts = pes_video_time; pes_video_time = -1.; return pts; } + double audio_pts() { double pts = pes_audio_time; pes_audio_time = -1.; return pts; } + void reset_pts(); + void set_audio_pts(uint64_t pts, const double denom); + void set_video_pts(uint64_t pts, const double denom); + int current_cell_no(); + }; + + class cacheframe_t { + public: + new_memset(0); + uint8_t *y, *u, *v; + int y_alloc, u_alloc, v_alloc; + int y_size, u_size, v_size; + int64_t frame_number; + uint32_t age; + + cacheframe_t() {} + ~cacheframe_t() {} + }; + + class cache_t { + int extend_cache(); + public: + new_memset(0); + cacheframe_t *frames; + int total; + int allocation; + uint32_t seq; + + cache_t() {} + ~cache_t(); + void clear(); + void reset() { total = 0; } + void put_frame(int64_t zframe_number, + uint8_t *zy, uint8_t *zu, uint8_t *zv, + int zy_size, int zu_size, int zv_size); + int get_frame( int64_t frame_number, + uint8_t **zy, uint8_t **zu, uint8_t **zv); + int has_frame(int64_t frame_number); + int64_t memory_usage(); + }; + + fs_t *fs; // Store entry path here + demuxer_t *demuxer; // Master title tables copied to all tracks + int iopened; // file opened by user (before init) + +// Media specific + + int total_atracks; + class atrack_t { + void extend_sample_offsets(); + public: + new_memset(0); + int channels; + int sample_rate; + demuxer_t *demuxer; + audio_t *audio; + int64_t current_position; + int64_t total_samples; + int format; // format of audio + int number, pid; + long nudge; + // If we got the header information yet. Used in streaming mode. + int got_header; + // Pointer to master table of contents when the TOC is read. + // Pointer to private table when the TOC is being created + // Stores the absolute byte of each audio chunk + int64_t *sample_offsets; + int total_sample_offsets; + int sample_offsets_allocated; + // If this sample offset table must be deleted by the track + int private_offsets; + // End of stream in table of contents construction + int64_t audio_eof; + // Starting byte of previous/current packet for making TOC + int64_t prev_offset, curr_offset; + double audio_time; // audio pts based time + int askip; // skipping + int64_t pts_position; // sample position at pts + double pts_origin; + double pts_starttime; // demuxer first pts + double pts_offset; // pts offset due to discontinuity + double frame_pts; + void reset_pts(); + double last_pts() { return pts_starttime+audio_time-pts_offset; } + + atrack_t(zmpeg3_t *zsrc, int custom_id, int format, demuxer_t *demux, int no); + ~atrack_t(); + + int calculate_format(zmpeg3_t *src); + int handle_audio_data(int track_number); + int handle_audio(int track_number); + int64_t track_position() { return current_position+nudge; } + void append_samples(int64_t offset); + void update_frame_pts() { if( frame_pts < 0 ) frame_pts = demuxer->audio_pts(); } + void update_audio_time(); + double get_audio_time(); + double pts_audio_time(double pts) { + return pts_starttime<0. ? pts_starttime : pts-pts_starttime+pts_offset; + } + int64_t apparent_position(); + } *atrack[MAX_STREAMZ]; + + int total_vtracks; + class vtrack_t { + void extend_frame_offsets(); + void extend_keyframe_numbers(); + public: + new_memset(0); + int width, height; + uint32_t tcode; + double frame_rate; + float aspect_ratio; + demuxer_t *demuxer; + video_t *video; // Video decoding object + long current_position; // Number of next frame to be played + long total_frames; // Total frames in the file + int number, pid; + slice_buffer_t *slice; // toc slice data + uint8_t *sbp; + int sb_size; + // Pointer to master table of contents when the TOC is read. + // Pointer to private table when the TOC is being created + // Stores the absolute byte of each frame + int64_t *frame_offsets; + int total_frame_offsets; + int frame_offsets_allocated; + int *keyframe_numbers; + int total_keyframe_numbers; + int keyframe_numbers_allocated; + // Starting byte of previous/current packet for making TOC + int64_t prev_frame_offset; + int64_t prev_offset, curr_offset; + int vskip; // skipping + double video_time; // reshuffled pts + // End of stream in table of contents construction + int64_t video_eof; + int got_top; + int got_keyframe; + cache_t *frame_cache; + // If these tables must be deleted by the track + int private_offsets; + int pts_position; // framenum at pts + double pts_origin; + double pts_starttime; // first pts + double pts_offset; // pts offset due to discontinuity + double refframe_pts; // last refframe pts + double frame_pts; + double pts_video_time(double pts) { + return pts_starttime<0. ? pts_starttime : pts-pts_starttime+pts_offset; + } + void reset_pts(); + double last_pts() { return pts_starttime+video_time-pts_offset; } + + vtrack_t(zmpeg3_t *zsrc, int custom_id, demuxer_t *demux, int no); + ~vtrack_t(); + + int handle_video_data(int track_number, int prev_data_size); + int handle_video(int track_number); + int find_keyframe_index(int64_t frame); + void append_frame(int64_t offset, int is_keyframe); + void update_frame_pts() { if( frame_pts < 0 ) frame_pts = demuxer->video_pts(); } + void update_video_time(); + double get_video_time(); + int apparent_position(); + } *vtrack[MAX_STREAMZ]; + + // Subtitle track + // Stores the program offsets of subtitle images. + // Only used for seeking off of table of contents for editing. + // Doesn't have its own demuxer but hangs off the video demuxer. + int total_stracks; + class strack_t { + void extend_offsets(); + void extend_subtitles(); + public: + new_memset(0); + zrwlock_t rwlock; + int id; // 0x2X + video_t *video; // if non-zero, decoder owns track + int64_t *offsets; // Offsets in program of subtitle packets + int total_offsets; + int allocated_offsets; + subtitle_t *subtitles[MAX_SUBTITLES]; // Last subtitle objects found in stream. + int total_subtitles; + + strack_t(int zid, video_t *vid=0); + strack_t(strack_t &strack); + ~strack_t(); + + int append_subtitle(subtitle_t *subtitle, int lock=1); + void append_subtitle_offset(int64_t program_offset); + void del_subtitle(subtitle_t *subtitle, int lock=0); + void del_subtitle(int i, int lock=0); + void del_all_subtitles(); + } *strack[MAX_STREAMZ]; + + static uint64_t get8bytes(uint8_t *buf) { + return bswap_64(*((uint64_t *)buf)); + } + static uint32_t get4bytes(uint8_t *buf) { + return bswap_32(*((uint32_t *)buf)); + } + static uint32_t get2bytes(uint8_t *buf) { + return bswap_16(*((uint16_t *)buf)); + } + + class icell_t { + public: + new_memset(0); + int64_t start_byte, end_byte; // Bytes relative to start of stream. + short vob_id, cell_id; // cell address vob/cell id + uint32_t inlv; // bit vector of allowed interleaves + short angle, discon; // angle interleave no, discontinuity flag + + int has_inlv(int i) { return (inlv >> i) & 1; } + }; + + class icell_table_t { + public: + icell_t *cells; + long total_cells; + long cells_allocated; + icell_table_t() { cells = 0; total_cells = cells_allocated = 0; } + ~icell_table_t(); + icell_t *append_cell(); + }; + + class ifo_t { + public: + new_memset(0); + enum ifo_id_type { + id_NUM_MENU_VOBS = 0, + id_NUM_TITLE_VOBS = 1, + id_MAT = 0, + id_PTT = 1, + id_TSP = 1, + id_TITLE_PGCI = 2, + id_MENU_PGCI = 3, + id_TMT = 4, + id_MENU_CELL_ADDR = 5, + id_MENU_VOBU_ADDR_MAP = 6, + id_TITLE_CELL_ADDR = 7, + id_TITLE_VOBU_ADDR_MAP = 8, + }; + + uint32_t num_menu_vobs; + uint32_t vob_start; + uint32_t empirical; // scan for audio/subtitle stream data + uint8_t *data[10]; + int fd; // file descriptor + int64_t pos; // offset of ifo file on device + int current_vob_id; + int max_inlv; + int64_t current_byte; +#include "ifo.h" + + int type_vts() { + return !strncmp((char*)data[id_MAT], "DVDVIDEO-VTS", 12) ? 0 : -1; + } + int type_vmg() { + return !strncmp((char*)data[id_MAT], "DVDVIDEO-VMG", 12) ? 0 : -1; + } + + void get_playlist(zmpeg3_t *zsrc); + int ifo_read(long pos, long count, uint8_t *data); + int read_mat(); + + ifo_t(int zfd, long zpos); + ~ifo_t(); + int ifo_close(); + int init_tables(); + int get_table(int64_t offset,unsigned long tbl_id); + void get_palette(zmpeg3_t *zsrc); + void get_header(demuxer_t *demux); + void get_playinfo(zmpeg3_t *zsrc, icell_table_t *icell_addrs); + void icell_addresses(icell_table_t *cell_addrs); + int64_t ifo_chapter_cell_time(zmpeg3_t *zsrc, int chapter); + void get_ititle(zmpeg3_t *zsrc, int chapter=0); + void icell_map(zmpeg3_t *zsrc, icell_table_t *icell_addrs); + int chk(int vts_title, int chapter, int inlv, int angle, + icell_table_t *icell_addrs, int §ors, int &pcells, int &max_angle); + }; + + // Table of contents storage + int64_t **frame_offsets; + int64_t **sample_offsets; + int **keyframe_numbers; + int64_t *video_eof; + int64_t *audio_eof; + int *total_frame_offsets; + int *total_sample_offsets; + int64_t *total_samples; + int *total_keyframe_numbers; + // Handles changes in channel count after the start of a stream + int *channel_counts, *nudging; + // Indexes for audio tracks + index_t **indexes; + int total_indexes; + double cell_time; // time at start of last cell + // toc/skim thumbnail data callback + zthumbnail_cb thumbnail_fn; + void *thumbnail_priv; + + // Number of bytes to devote to the index of a single track + // in the index building process. + int64_t index_bytes; + int file_type, log_errs; + int err_logging(int v=-1) { int lv = log_errs; if( v>=0 ) log_errs=v; return lv; } + // Only one of these is set to 1 to specify what kind of stream we have. + int is_transport_stream() { return file_type & FT_TRANSPORT_STREAM; } + int is_program_stream() { return file_type & FT_PROGRAM_STREAM; } + int is_audio_stream() { return file_type & FT_AUDIO_STREAM; } // Elemental stream + int is_video_stream() { return file_type & FT_VIDEO_STREAM; } // Elemental stream + int is_ifo_file() { return file_type & FT_IFO_FILE; } // dvd ifo file + // Special kind of transport stream for BD or AVC-HD + int is_bd() { return 0; /* file_type & FT_BD_FILE; */ } + int packet_size; // > 0 if known otherwise determine empirically for every packet + // Type and stream for getting current absolute byte + int last_type_read; // 1 - audio 2 - video + int last_stream_read; + int vts_title; // video titleset title number (counting from 0) + int total_vts_titles; + int interleave, angle; // active program sector interleave/angle index + int total_interleaves; + int cpus; // number of decode threads + int seekable; // Filesystem is seekable. Also means the file isn't a stream. + int last_cell_no; // last known cell no in TOC build + int pts_padding; // use pts data to add padding to sync damaged data + FILE *toc_fp; // For building TOC, the output file. + int recd_fd; // record file + int64_t recd_pos; // record file size + /* The first color palette in the IFO file. Used for subtitles. + * Byte order: YUVX * 16 */ + int have_palette; + uint8_t palette[16 * 4]; + // Date of source file index was created from. + // Used to compare DVD source file to table of contents source. + int64_t source_date; + // playback cell table + icell_table_t *playinfo; + + int calculate_packet_size(); + int get_file_type(int *toc_atracks, int *toc_vtracks, const char *title_path); + int read_toc(int *toc_atracks, int *toc_vtracks, const char *title_path); + enum { show_toc_SAMPLE_OFFSETS=1, show_toc_AUDIO_INDEX=2, show_toc_FRAME_OFFSETS=4 }; + int show_toc(int flags); + int handle_nudging(); + void divide_index(int track_number); + int update_index(int track_number,int flush); + static ifo_t *ifo_open(int fd,long pos); + int read_ifo(); + atrack_t *new_atrack_t(int custom_id, int format, + demuxer_t *demux, int number); + vtrack_t *new_vtrack_t(int custom_id, demuxer_t *demux, int number); + audio_t *new_audio_t(atrack_t *ztrack, int zformat); + video_t *new_video_t(vtrack_t *ztrack); + strack_t* get_strack_id(int id, video_t *vid); + strack_t* get_strack(int number); + strack_t* create_strack(int id, video_t *vid=0); + int display_subtitle(int stream, int sid, int id, + uint8_t *yp, uint8_t *up, uint8_t *vp, uint8_t *ap, + int x, int y, int w, int h, double start_msecs, double stop_msecs); + int delete_subtitle(int stream, int sid, int id); + static int clip(int v, int mn, int mx) { + if( v > mx ) return mx; + if( v < mn ) return mn; + return v; + } + static uint8_t clip(int32_t v) { + return ((uint8_t)v) == v ? v : clip(v,0,255); + } + void handle_subtitle(); + void handle_cell(int this_cell_no); + +#ifdef ZDVB + class dvb_t { + uint8_t *xbfr, *eob; + uint32_t get8bits() { return xbfr < eob ? *xbfr++ : 0; } + uint32_t get16bits() { uint32_t v = get8bits(); return (v<<8) | get8bits(); } + uint32_t get24bits() { uint32_t v = get16bits(); return (v<<8) | get8bits(); } + uint32_t get32bits() { uint32_t v = get24bits(); return (v<<8) | get8bits(); } + public: + class mgt_t; // master guide table + class vct_t; // virtual channel table + class rrt_t; // rating region table + class eit_t; // event information table + class ett_t; // extended text table + class stt_t; // system time table + + class mgt_t { + public: + new_memset(0); + + dvb_t *dvb; + uint32_t ver; + int items; + class mitem_t { + public: + new_memset(0); + uint8_t *bfr; + int bfr_size, bfr_alloc; + int src_id, tbl_id, tbl_len; + uint16_t type; + uint16_t pid; + uint32_t version; + uint32_t size; + void init(int len); + void clear(); + void extract(uint8_t *dat, int len); + int bfr_len() { return tbl_len - bfr_size; } + mitem_t() {} + mitem_t(int zpid) : pid(zpid) { bfr=0; bfr_size=bfr_alloc=0; } + ~mitem_t() { clear(); } + } *mitems; + void clear(); + void extract(); + mitem_t *search(uint16_t pid); + mgt_t(dvb_t *p) : dvb(p) {} + ~mgt_t() { clear(); } + } *mgt; + + class vct_t { + public: + new_memset(0); + class vitem_t; + + dvb_t *dvb; + uint32_t version; + uint32_t transport_stream_id; + int items, items_allocated; + + class vitem_t { + public: + new_memset(0); + class ch_elts_t; + + uint16_t short_name[7+1]; + uint32_t major_channel_number; + uint32_t minor_channel_number; + uint32_t modulation_mode; + uint32_t carrier_frequency; + uint32_t channel_TSID; + uint32_t program_number; + uint32_t etm_location; + uint8_t access_controlled; + uint8_t hidden; + uint8_t path_select; + uint8_t out_of_band; + uint32_t service_type; + uint32_t source_id; + uint32_t pcr_pid; + int num_ch_elts; + class ch_elts_t { + public: + uint32_t stream_id; + uint32_t pes_pid; + uint8_t code_639[3]; + void extract(dvb_t *dvb); + } elts[10]; + void extract(dvb_t *dvb); + } **vct_tbl; + + vct_t(dvb_t *p) : dvb(p) {} + ~vct_t() { clear(); } + void extract(); + void clear(); + int search(vitem_t &new_item); + void append(vitem_t &new_item); + } *tvct, *cvct; + + class rrt_t { + public: + new_memset(0); + class ritem_t; + + dvb_t *dvb; + uint32_t version; + uint8_t region_nlen; + uint8_t region_name[2*32+1]; + int items; + + class ritem_t { + public: + new_memset(0); + class rating_vt; + + uint8_t dim_nlen; + uint8_t dim_name[2*20+1]; + uint8_t graduated_scale; + uint8_t num_values; + class rating_vt { + public: + uint8_t rating_nlen; + uint8_t rating_name[2*8+1]; + uint8_t rating_tlen; + uint8_t rating_text[2*150+1]; + void extract(dvb_t *dvb); + } *abrevs; + void extract(dvb_t *dvb); + void clear(); + ritem_t() {} + ~ritem_t() { clear(); } + } *ratings; + + rrt_t(dvb_t *p) : dvb(p) {} + ~rrt_t() { clear(); } + void extract(); + void clear(); + } *rrt; + + class eit_t { + public: + new_memset(0); + class einfo_t; + + dvb_t *dvb; + eit_t *next; + int id; + uint32_t version; + uint32_t source_id; + int items, nitems; + + class einfo_t { + public: + new_memset(0); + uint16_t event_id; + uint16_t location; + uint32_t start_time; + uint32_t seconds; + uint8_t title_tlen; + uint8_t *title_text; + void extract(dvb_t *dvb); + void clear(); + einfo_t() {} + ~einfo_t() { clear(); } + } *infos; + + eit_t(dvb_t *p, int id) : dvb(p), id(id) {} + ~eit_t() { clear(); } + void extract(); + int search(uint16_t evt_id); + void clear(); + } *eit; + + class ett_t { + public: + new_memset(0); + class etext_t; + + dvb_t *dvb; + ett_t *next; + int id; + + class etext_t { + public: + new_memset(0); + + etext_t *next; + int id; + uint32_t version; + uint16_t table_id; + uint32_t etm_id; + uint16_t msg_tlen; + uint8_t *msg_text; + void extract(dvb_t *dvb, uint32_t eid); + void clear(); + etext_t(int id) : id(id) {} + ~etext_t() { clear(); } + } *texts; + + ett_t(dvb_t *p, int id) : dvb(p), id(id) {} + ~ett_t() { clear(); } + void extract(); + void clear(); + } *ett; + + class stt_t { + dvb_t *dvb; + public: + new_memset(0); + + uint32_t version; + uint16_t table_id; + uint32_t system_time; + uint8_t utc_offset; + uint16_t daylight_saving; + + stt_t(dvb_t *p) : dvb(p) {} + ~stt_t() { clear(); } + void extract(); + void clear(); + } *stt; + + uint32_t stt_start_time; + int64_t stt_offset() { + return (365*10+7)*24*3600L - (stt ? stt->utc_offset : 0); + } + + int64_t get_system_time() { + return stt && stt->system_time ? stt->system_time + stt_offset() : -1; + } + zmpeg3_t *src; + int sect_len; + int stream_id; + uint32_t version; + int cur_next; + int sect_num; + int proto_ver; + int empirical; + + int bfr_pos() { return xbfr - active->bfr; } + int bfr_len() { return active->bfr_size - bfr_pos(); } + void skip_bfr(int n); + void skp_bfr(int n) { if( n > 0 ) skip_bfr(n); } + + int text_length, text_allocated; + char *text; + int get_text(uint8_t *dat, int bytes); + void append_text(char *dat, int bytes); + char *mstring(uint8_t *bp, int len); + + dvb_t(zmpeg3_t *zsrc); + ~dvb_t(); + void reset(); + void extract(); + + mgt_t::mitem_t *active; + mgt_t::mitem_t *atsc_pid(int pid); + mgt_t::mitem_t base_pid; + + int atsc_tables(demuxer_t *demux, int pid); + void skip_descr(int descr_len); + + int channel_count(); + int signal_time(); + int get_channel(int n, int &major, int &minor); + int get_station_id(int n, char *name); + int total_astreams(int n, int &count); + int astream_number(int n, int ord, int &stream, char *enc=0); + int total_vstreams(int n, int &count); + int vstream_number(int n, int ord, int &stream); + int read_dvb(demuxer_t *demux); + int get_chan_info(int n, int ord, int i, char *txt, int len); + } dvb; + +#endif + + // Interface + + // Get version information + static int zmajor() { return ZMPEG3_MAJOR; }; + static int zminor() { return ZMPEG3_MINOR; }; + static int zrelease() { return ZMPEG3_RELEASE; }; + + // Check for file compatibility. Return 1 if compatible. + static int check_sig(char *path); + + // Open the MPEG stream. + // An error code is put into *ret if it fails and error_return is nonzero. + zmpeg3_t(const char *path); + zmpeg3_t(const char *path, int &ret, int access=fs_t::io_UNBUFFERED, const char *title_path=0); + zmpeg3_t(int fd, int &ret, int access=0); + zmpeg3_t(FILE *fp, int &ret, int access=0); + int init(const char *title_path=0); + ~zmpeg3_t(); + + // Performance + int set_cpus(int cpus); + int set_pts_padding(int v); + + // Query the MPEG3 stream about audio. + int has_audio(); + int total_astreams(); + int audio_channels(int stream); + double sample_rate(int stream); + const char *audio_format(int stream); + + // Total length obtained from the timecode. + // For DVD files, this is unreliable. + long audio_nudge(int stream); + long audio_samples(int stream); + int set_sample(long sample, int stream); + long get_sample(int stream); + + // Stream defines the number of the multiplexed stream to read. + // If output argument is null the audio is not rendered. + // Read a PCM buffer of audio from 1 channel and advance the position. + int read_audio(void *output_v, int type, int channel, long samples, int stream); + int read_audio(double *output_d, int channel, long samples, int stream); + int read_audio(float *output_f, int channel, long samples, int stream); + int read_audio(int *output_i, int channel, long samples, int stream); + int read_audio(short *output_s, int channel, long samples, int stream); + // Read a PCM buffer of audio from 1 channel without advancing the position. + int reread_audio(void *output_v, int type, int channel, long samples, int stream); + int reread_audio(double *output_d, int channel, long samples, int stream); + int reread_audio(float *output_f, int channel, long samples, int stream); + int reread_audio(int *output_i, int channel, long samples, int stream); + int reread_audio(short *output_s, int channel, long samples, int stream); + + // Read the next compressed audio chunk. Store the size in size and return a + // Stream defines the number of the multiplexed stream to read. + int read_audio_chunk(uint8_t *output, long *size, long max_size, int stream); + + // Query the stream about video. + int has_video(); + int total_vstreams(); + int video_width(int stream); + int video_height(int stream); + int coded_width(int stream); + int coded_height(int stream); + int video_pid(int stream); + float aspect_ratio(int stream); // aspect ratio. 0 if none + double frame_rate(int stream); // Frames/sec + + long video_frames(int stream); // total length - for TOC files only. + int set_frame(long frame, int stream); // Seek to a frame + // int skip_frames(); /*???*/ + long get_frame(int stream); // Tell current position + + // Total bytes. Used for absolute byte seeking. + int64_t get_bytes(); + + // Seek all the tracks to the absolute byte in the + // file. This eliminates the need for tocs but doesn't + // give frame accuracy. + int seek_byte(int64_t byte); + int64_t tell_byte(); + + int previous_frame(int stream); + int end_of_audio(int stream); + int end_of_video(int stream); + + // Give the seconds time in the last packet read + double get_time(); + double get_audio_time(int stream); + double get_video_time(int stream); + int get_cell_time(int no, double &time); + + // Read input frame and scale to the output frame + // The last row of **output_rows must contain 4 extra bytes for scratch work. + int read_frame(uint8_t **output_rows, // row start pointers + int in_x, int in_y, int in_w, int in_h, // Location in input frame + int out_w, int out_h, // Dimensions of output_rows + int color_model, int stream); + + // Get the colormodel being used natively by the stream + int colormodel(int stream); + // Set the row stride to be used in read_yuvframe + int set_rowspan(int bytes, int stream); + + // Read a frame in the native color model used by the stream. + // The Y, U, and V planes are copied into the y, u, and v + // BUFFERS Provided. + // The input is cropped to the dimensions given but not scaled. + int read_yuvframe(char *y_output, char *u_output, char *v_output, + int in_x, int in_y, int in_w, int in_h, int stream); + + // Read a frame in the native color model used by the stream. + // The Y, U, and V planes are not copied but the _output pointers + // are redirected to the frame buffer. + int read_yuvframe_ptr(char **y_output, char **u_output, char **v_output, + int stream); + + // Drop frames number of frames + int drop_frames(long frames, int stream); + + // Read the next compressed frame including headers. + // Store the size in size and return a 1 if error. + // Stream defines the number of the multiplexed stream to read. + int read_video_chunk(uint8_t *output, long *size, long max_size, + int stream); + + // Master control + int get_total_vts_titles(); + int set_vts_title(int title=-1); + int get_total_interleaves(); + int set_interleave(int inlv=-1); + int set_angle(int a=-1); + int set_program(int no); // legacy + + // Memory used by video caches. + int64_t memory_usage(); + // write incoming datastream on file descr fd + // buffer access must be io_THREADED. useful to record dvb device data + // bsz records up to bsz bytes of past buffer data in write_align + int start_record(int fd, int bsz=0); + int stop_record(); + void write_record(uint8_t *data, int len); + // limit position for start of last full packet + int64_t record_position() { return recd_pos - packet_size + 1; } + // restart streams, discard device buffer and reinit file positions + void restart(); + // enable/disable data xfr from reader thread + int pause_reader(int v); + + // subtitle functions + // get number of subtitle tracks + int subtitle_tracks() { return total_stracks; } + // Enable overlay of a subtitle track. + // track - the number of the subtitle track starting from 0 + // The same subtitle track is overlayed for all video tracks. + // track=-1 to disable subtitles. + int show_subtitle(int stream, int strk); + + // Table of contents generation + // Begin constructing table of contents + static zmpeg3_t *start_toc(const char *path, const char *toc_path, + int program=0, int64_t *total_bytes=0); + // Set the maximum number of bytes per index track + void set_index_bytes(int64_t bytes) { index_bytes = bytes; } + // Process one packet + int do_toc(int64_t *bytes_processed); + // Write table of contents + void stop_toc(); + int set_thumbnail_callback(int trk, int skim, int thumb, zthumbnail_cb fn, void *p); + int get_thumbnail(int trk, int64_t &frn, uint8_t *&t, int &w, int &h); + int set_cc_text_callback(int trk, zcc_text_cb fn); + + // Get modification date of source file from table of contents. + // Used to compare DVD source file to table of contents source. + int64_t get_source_date() { return source_date; } + // Get modification date of source file from source file. + static int64_t calculate_source_date(char *path); + static int64_t calculate_source_date(int fd); + // Table of contents queries + int index_tracks(); + int index_channels(int track); + int index_zoom(); + int index_size(int track); + float* index_data(int track, int channel); + // Returns 1 if the file has a table of contents + int has_toc() { + return frame_offsets || sample_offsets ? 1 : 0; + } + // Return the path of the title number or 0 if no more titles. + char* title_path(int number) { + return number>=0 && numbertotal_titles ? + demuxer->titles[number]->fs->path : 0; + } + + static inline void complete_path(char *full_path, char *path) { + char dir[zmpeg3_t::STRLEN]; + if( path[0] != '/' && getcwd(dir, sizeof(dir)) ) + sprintf(full_path, "%s/%s", dir, path); + else + strcpy(full_path, path); + } + + static inline void get_directory(char *directory, char *path) { + char *ptr = strrchr(path, '/'); + int i = 0; + if( ptr ) { + int n = ptr-path; + while( i < n ) { + directory[i] = path[i]; + ++i; + } + } + if( i == 0 ) directory[i++] = '.'; + directory[i] = 0; + } + + static inline void get_filename(char *filename, char *path) { + char *ptr = strrchr(path, '/'); + if( ptr ) ++ptr; + else ptr = path; + strcpy(filename, ptr); + } + + static inline void joinpath(char *path, char *dir, char *filename) { + sprintf(path, "%s/%s", dir, filename); + } + + static inline int64_t path_total_bytes(char *path) { + struct stat64 st; + return stat64(path, &st )<0 ? 0 : st.st_size; + } + +}; + +typedef zmpeg3_t::zlock_t zzlock_t; +typedef zmpeg3_t::zblock_t zzblock_t; +typedef zmpeg3_t::zrwlock_t zzrwlock_t; +typedef zmpeg3_t::fs_t zfs_t; +typedef zfs_t::css_t zcss_t; +typedef zcss_t::key_t zkey_t; +typedef zcss_t::blk_t zblk_t; +typedef zcss_t::playkey_t zplaykey_t; +typedef zfs_t::buffer_t zbuffer_t; +typedef zmpeg3_t::bits_t zbits_t; +typedef zmpeg3_t::index_t zindex_t; +typedef zmpeg3_t::bitfont_t zbitfont_t; +typedef zbitfont_t::bitchar_t zbitchar_t; +typedef zbitfont_t::static_init_t zstatic_init_t; +typedef zmpeg3_t::timecode_t ztimecode_t; +typedef zmpeg3_t::audio_t zaudio_t; +typedef zaudio_t::imdct_complex_t zimdct_complex_t; +typedef zaudio_t::imdct_al_table_t zimdct_al_table_t; +typedef zaudio_t::audio_decoder_layer_t zaudio_decoder_layer_t; +typedef zaudio_t::audio_decoder_ac3_t zaudio_decoder_ac3_t; +typedef zaudio_t::audio_decoder_pcm_t zaudio_decoder_pcm_t; +typedef zmpeg3_t::VLCtab_t zVLCtab_t; +typedef zmpeg3_t::DCTtab_t zDCTtab_t; +typedef zmpeg3_t::slice_buffer_t zslice_buffer_t; +typedef zmpeg3_t::video_t zvideo_t; +typedef zvideo_t::cc_t zcc_t; +typedef zcc_t::svc_t zsvc_t; +typedef zsvc_t::win_t zwin_t; +typedef zsvc_t::chr_t zchr_t; +typedef zmpeg3_t::slice_decoder_t zslice_decoder_t; +typedef zmpeg3_t::subtitle_t zsubtitle_t; +typedef zmpeg3_t::demuxer_t zdemuxer_t; +typedef zdemuxer_t::zstream_t zzstream_t; +typedef zdemuxer_t::title_t ztitle_t; +typedef ztitle_t::cell_t zcell_t; +typedef zmpeg3_t::cacheframe_t zcacheframe_t; +typedef zmpeg3_t::cache_t zcache_t; +typedef zmpeg3_t::atrack_t zatrack_t; +typedef zmpeg3_t::vtrack_t zvtrack_t; +typedef zmpeg3_t::strack_t zstrack_t; +typedef zmpeg3_t::icell_t zicell_t; +typedef zmpeg3_t::icell_table_t zicell_table_t; +typedef zmpeg3_t::ifo_t zifo_t; +#ifdef ZDVB +typedef zmpeg3_t::dvb_t zdvb_t; +typedef zdvb_t::mgt_t zmgt_t; +typedef zmgt_t::mitem_t zmitem_t; +typedef zdvb_t::vct_t zvct_t; +typedef zvct_t::vitem_t zvitem_t; +typedef zvitem_t::ch_elts_t zch_elts_t; +typedef zdvb_t::rrt_t zrrt_t; +typedef zrrt_t::ritem_t zritem_t; +typedef zritem_t::rating_vt zrating_vt; +typedef zdvb_t::eit_t zeit_t; +typedef zeit_t::einfo_t zeinfo_t; +typedef zdvb_t::ett_t zett_t; +typedef zett_t::etext_t zetext_t; +typedef zdvb_t::stt_t zstt_t; +#endif + +/* legacy */ +extern "C" { +#else +typedef struct {} zmpeg3_t; +#endif /*__cplusplus */ +typedef zmpeg3_t mpeg3_t; + +int mpeg3_major(void); +int mpeg3_minor(void); +int mpeg3_release(void); +int mpeg3_check_sig(char *path); +int mpeg3_is_program_stream(zmpeg3_t * zsrc); +int mpeg3_is_transport_stream(zmpeg3_t * zsrc); +int mpeg3_is_video_stream(zmpeg3_t * zsrc); +int mpeg3_is_audio_stream(zmpeg3_t * zsrc); +int mpeg3_is_ifo_file(zmpeg3_t * zsrc); +int mpeg3_create_title(zmpeg3_t * zsrc,int full_scan); +zmpeg3_t *mpeg3_open(const char *path,int *error_return); +zmpeg3_t *mpeg3_open_title(const char *title_path,const char *path,int *error_return); +zmpeg3_t *mpeg3_zopen(const char *title_path,const char *path,int *error_return, int access); +zmpeg3_t *mpeg3_open_copy(const char *path,zmpeg3_t *old_src,int *error_return); +int mpeg3_close(zmpeg3_t *zsrc); +int mpeg3_set_pts_padding(zmpeg3_t *zsrc, int v); +int mpeg3_set_cpus(zmpeg3_t *zsrc,int cpus); +int mpeg3_has_audio(zmpeg3_t *zsrc); +int mpeg3_total_astreams(zmpeg3_t *zsrc); +int mpeg3_audio_channels(zmpeg3_t *zsrc,int stream); +int mpeg3_sample_rate(zmpeg3_t *zsrc,int stream); +const char *mpeg3_audio_format(zmpeg3_t *zsrc,int stream); +long mpeg3_get_audio_nudge(zmpeg3_t *zsrc,int stream); +long mpeg3_audio_samples(zmpeg3_t *zsrc,int stream); +int mpeg3_set_sample(zmpeg3_t *zsrc,long sample,int stream); +long mpeg3_get_sample(zmpeg3_t *zsrc,int stream); +int mpeg3_read_audio(zmpeg3_t *zsrc,float *output_f,short *output_i,int channel, + long samples,int stream); +int mpeg3_read_audio_d(zmpeg3_t *zsrc,double *output_d, int channel, + long samples, int stream); +int mpeg3_read_audio_f(zmpeg3_t *zsrc,float *output_f, int channel, + long samples, int stream); +int mpeg3_read_audio_i(zmpeg3_t *zsrc,int *output_i, int channel, + long samples, int stream); +int mpeg3_read_audio_s(zmpeg3_t *zsrc,short *output_s, int channel, + long samples, int stream); +int mpeg3_reread_audio_d(zmpeg3_t *zsrc,double *output_d, int channel, + long samples, int stream); +int mpeg3_reread_audio_f(zmpeg3_t *zsrc,float *output_f, int channel, + long samples, int stream); +int mpeg3_reread_audio_i(zmpeg3_t *zsrc,int *output_i, int channel, + long samples, int stream); +int mpeg3_reread_audio_s(zmpeg3_t *zsrc,short *output_s, int channel, + long samples, int stream); +int mpeg3_reread_audio(zmpeg3_t *zsrc,float *output_f,short *output_i, + int channel,long samples,int stream); +int mpeg3_read_audio_chunk(zmpeg3_t *zsrc,unsigned char *output,long *size, + long max_size,int stream); +int mpeg3_has_video(zmpeg3_t *zsrc); +int mpeg3_total_vstreams(zmpeg3_t *zsrc); +int mpeg3_video_width(zmpeg3_t *zsrc,int stream); +int mpeg3_video_height(zmpeg3_t *zsrc,int stream); +int mpeg3_coded_width(zmpeg3_t *zsrc,int stream); +int mpeg3_coded_height(zmpeg3_t *zsrc,int stream); +int mpeg3_video_pid(zmpeg3_t *zsrc,int stream); +float mpeg3_aspect_ratio(zmpeg3_t *zsrc,int stream); +double mpeg3_frame_rate(zmpeg3_t *zsrc,int stream); +long mpeg3_video_frames(zmpeg3_t *zsrc,int stream); +int mpeg3_set_frame(zmpeg3_t *zsrc,long frame,int stream); +//int mpeg3_skip_frames(zmpeg3_t *zsrc); +long mpeg3_get_frame(zmpeg3_t *zsrc,int stream); +int64_t mpeg3_get_bytes(zmpeg3_t *zsrc); +int mpeg3_seek_byte(zmpeg3_t *zsrc,int64_t byte); +int64_t mpeg3_tell_byte(zmpeg3_t *zsrc); +int mpeg3_previous_frame(zmpeg3_t *zsrc,int stream); +int mpeg3_end_of_audio(zmpeg3_t *zsrc,int stream); +int mpeg3_end_of_video(zmpeg3_t *zsrc,int stream); +double mpeg3_get_time(zmpeg3_t *zsrc); +double mpeg3_get_audio_time(zmpeg3_t *zsrc, int stream); +double mpeg3_get_video_time(zmpeg3_t *zsrc, int stream); +double mpeg3_get_cell_time(zmpeg3_t *zsrc, int no, double *time); +int mpeg3_read_frame(zmpeg3_t *zsrc,unsigned char **output_rows,int in_x, + int in_y,int in_w,int in_h,int out_w,int out_h,int color_model,int stream); +int mpeg3_colormodel(zmpeg3_t *zsrc,int stream); +int mpeg3_set_rowspan(zmpeg3_t *zsrc,int bytes,int stream); +int mpeg3_read_yuvframe(zmpeg3_t *zsrc,char *y_output,char *u_output, + char *v_output,int in_x,int in_y,int in_w,int in_h,int stream); +int mpeg3_read_yuvframe_ptr(zmpeg3_t *zsrc,char **y_output,char **u_output, + char **v_output,int stream); +int mpeg3_drop_frames(zmpeg3_t *zsrc,long frames,int stream); +int mpeg3_read_video_chunk(zmpeg3_t *zsrc,unsigned char *output,long *size, + long max_size,int stream); +int mpeg3_get_total_vts_titles(zmpeg3_t *zsrc); +int mpeg3_set_vts_title(zmpeg3_t *zsrc,int title); // toc build only +int mpeg3_get_total_interleaves(zmpeg3_t *zsrc); +int mpeg3_set_interleave(zmpeg3_t *zsrc,int inlv); // toc build only +int mpeg3_set_angle(zmpeg3_t *zsrc,int a); // toc build only +int mpeg3_set_program(zmpeg3_t *zsrc,int no); // toc build only +int64_t mpeg3_memory_usage(zmpeg3_t *zsrc); +int mpeg3_get_thumbnail(zmpeg3_t *zsrc, int trk, + int64_t *frn, uint8_t **t, int *w, int *h); +int mpeg3_set_thumbnail_callback(zmpeg3_t *zsrc, int trk, + int skim, int thumb, zthumbnail_cb fn, void *p); +int mpeg3_set_cc_text_callback(zmpeg3_t *zsrc, int trk, zcc_text_cb fn); +int mpeg3_subtitle_tracks(zmpeg3_t *zsrc); +int mpeg3_show_subtitle(zmpeg3_t *zsrc,int vtrk, int strk); +int mpeg3_display_subtitle(zmpeg3_t *zsrc,int stream,int sid,int id, + uint8_t *yp,uint8_t *up,uint8_t *vp,uint8_t *ap, + int x,int y,int w,int h,double start_msecs,double stop_msecs); +int mpeg3_delete_subtitle(zmpeg3_t *zsrc,int stream,int sid,int id); +zmpeg3_t *mpeg3_start_toc(char *path,char *toc_path,int program,int64_t *total_bytes); +void mpeg3_set_index_bytes(zmpeg3_t *zsrc,int64_t bytes); +int mpeg3_do_toc(zmpeg3_t *zsrc,int64_t *bytes_processed); +void mpeg3_stop_toc(zmpeg3_t *zsrc); +int64_t mpeg3_get_source_date(zmpeg3_t *zsrc); +int64_t mpeg3_calculate_source_date(char *path); +int mpeg3_index_tracks(zmpeg3_t *zsrc); +int mpeg3_index_channels(zmpeg3_t *zsrc,int track); +int mpeg3_index_zoom(zmpeg3_t *zsrc); +int mpeg3_index_size(zmpeg3_t *zsrc,int track); +float *mpeg3_index_data(zmpeg3_t *zsrc,int track,int channel); +int mpeg3_has_toc(zmpeg3_t *zsrc); +char *mpeg3_title_path(zmpeg3_t *zsrc,int number); +// hooks needed for quicktime +typedef struct {} mpeg3_layer_t; +int mpeg3audio_dolayer3(mpeg3_layer_t *audio, + char *frame, int frame_size, float **output, int render); +int mpeg3_layer_header(mpeg3_layer_t *layer_data, unsigned char *data); +void mpeg3_layer_reset(mpeg3_layer_t *zlayer_data); +mpeg3_layer_t* mpeg3_new_layer(); +void mpeg3_delete_layer(mpeg3_layer_t *audio); +// hooks needed for mplexlo +void mpeg3_skip_video_frame(mpeg3_t *zsrc, int stream); +int64_t mpeg3_video_tell_byte(mpeg3_t *zsrc, int stream); +int64_t mpeg3_audio_tell_byte(mpeg3_t *zsrc, int stream); +#ifdef ZDVB +int mpeg3_dvb_channel_count(zmpeg3_t *zsrc); +int mpeg3_dvb_get_channel(mpeg3_t *zsrc,int n, int *major, int *minor); +int mpeg3_dvb_get_station_id(mpeg3_t *zsrc,int n, char *name); +int mpeg3_dvb_total_astreams(mpeg3_t *zsrc,int n, int *count); +int mpeg3_dvb_astream_number(mpeg3_t *zsrc,int n, int ord, int *stream, char *enc); +int mpeg3_dvb_total_vstreams(mpeg3_t *zsrc,int n, int *count); +int mpeg3_dvb_vstream_number(mpeg3_t *zsrc,int n, int ord, int *stream); +int mpeg3_dvb_get_chan_info(mpeg3_t *zsrc,int n, int ord, int i, char *cp, int len); +int mpeg3_dvb_get_system_time(mpeg3_t *zsrc, int64_t *tm); +#endif +#ifdef __cplusplus +} +#endif +#endif