aboutsummaryrefslogtreecommitdiff
path: root/Src/nsv/nsvlib.h
diff options
context:
space:
mode:
Diffstat (limited to 'Src/nsv/nsvlib.h')
-rw-r--r--Src/nsv/nsvlib.h364
1 files changed, 364 insertions, 0 deletions
diff --git a/Src/nsv/nsvlib.h b/Src/nsv/nsvlib.h
new file mode 100644
index 00000000..b773d996
--- /dev/null
+++ b/Src/nsv/nsvlib.h
@@ -0,0 +1,364 @@
+/*
+** nsvlib.h - NSV file/bitstream reading/writing interface
+**
+** Copyright (C) 2001-2002 Nullsoft, Inc.
+**
+** Confidential Subject to NDA
+*/
+
+#ifndef _NSVLIB_H_
+#define _NSVLIB_H_
+
+/*********************************************************************
+** bitstream classes
+*/
+
+#include "nsvbs.h"
+
+
+/*********************************************************************
+** NSV packeting limits
+*/
+#define NSV_MAX_AUDIO_LEN 0x8000 // 32kb
+#define NSV_MAX_VIDEO_LEN 0x80000 // 512kb
+#define NSV_MAX_AUX_LEN 0x8000 // 32kb for each aux stream
+#define NSV_MAX_AUXSTREAMS 15 // 15 aux streams maximum
+
+
+/*********************************************************************
+** Constants for setting certain metadata items using addHdrMetaData()
+*/
+#define METADATANAME_AUTHOR "Author"
+#define METADATANAME_TITLE "Title"
+#define METADATANAME_COPYRIGHT "Copyright"
+#define METADATANAME_COMMENT "Comment"
+#define METADATANAME_PROFILE "Profile"
+#define METADATANAME_FILEID "File ID"
+
+/*********************************************************************
+** NSV type utility functions/macros
+*/
+
+/*
+** Use NSV_MAKETYPE() to quickly make NSV audio/video/aux types.
+** ex: NSV_MAKETYPE('R','G','B','A')
+*/
+#define NSV_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24))
+
+/*
+** These functions convert types to and from strings.
+*/
+
+/* nsv_type_to_string() converts an NSV type to a string.
+ * out must be at least 5 bytes long. If 't' is not a valid type,
+ * then out will be set to an empty string
+ * ex:
+ * char out[5];
+ * nsv_type_to_string(NSV_MAKETYPE('R','G','B','A'),out);
+ * strcmp(out,"RGBA") == 0
+ */
+void nsv_type_to_string(unsigned int t, char *out);
+
+/* nsv_string_to_type() converts a string to an NSV type.
+ * Returns 0 if the type is not valid.
+ * ex: nsv_string_to_type("RGBA") == NSV_MAKETYPE('R','G','B','A')
+ */
+unsigned int nsv_string_to_type(char *in);
+
+
+/*********************************************************************
+** NSV bitstream packeting/unpacketing classes
+*/
+
+
+/* nsv_Packeter is used to packet audio/video/auxiliary data into
+ * a bitstream.
+ *
+ * ex:
+ * nsv_Packeter p;
+ * nsv_OutBS bs;
+ * p.setVidFmt(NSV_MAKETYPE('R','G','B','A'),320,240,30.0);
+ * p.setAudFmt(NSV_MAKETYPE('P','C','M',' '));
+ * for (;;) {
+ * doEncodeAudioAndVideo();
+ * p.setSyncFrame(is_keyframe);
+ * p.setSyncOffset(av_sync_offset);
+ * p.setAudio(audio_data,audio_len);
+ * p.setVideo(video_data,video_len);
+ * p.clearAuxChannels(); // you can add aux channels if you want
+ * if (p.packet(bs)) error();
+ * int outbuflen;
+ * void *outbuf=bs.get(&outbuflen);
+ * fwrite(outbuf,outbuflen,1,fp); // write output
+ * bs.clear(); // clear bitstream
+ * }
+ *
+ */
+
+class nsv_Packeter {
+ public:
+ nsv_Packeter();
+ ~nsv_Packeter();
+
+ // init (per file) calls
+ void setVidFmt(unsigned int vfmt, unsigned int w, unsigned int h, double frt);
+ void setAudFmt(unsigned int afmt) { audfmt=afmt; }
+
+ // per frame calls
+ void setSyncFrame(int is_syncframe) { is_sync_frame=is_syncframe; }
+ void setSyncOffset(int syncoffs) { syncoffset_cur=syncoffs; }
+ void setAudio(void *a, int a_len) { audio=a; audio_len=a_len; }
+ void setVideo(void *v, int v_len) { video=v; video_len=v_len; }
+ int addAuxChannel(unsigned int fmt, void *data, int data_len) // 0 on success
+ {
+ if (aux_used >= NSV_MAX_AUXSTREAMS) return -1;
+ aux[aux_used]=data;
+ aux_len[aux_used]=data_len;
+ aux_types[aux_used]=fmt;
+ aux_used++;
+ return 0;
+ }
+ void clearAuxChannels() { aux_used=0; }
+
+ int packet(nsv_OutBS &bs); // returns 0 on success
+
+ // some utility getting functions
+ unsigned int getAudFmt() { return audfmt; }
+ unsigned int getVidFmt() { return vidfmt; }
+ unsigned int getWidth() { return width; }
+ unsigned int getHeight() { return height; }
+ double getFrameRate() { return framerate; }
+
+ private:
+ unsigned char framerate_idx;
+ unsigned int vidfmt;
+ unsigned int audfmt;
+ unsigned int width;
+ unsigned int height;
+ double framerate;
+ int syncoffset_cur;
+
+ int aux_used;
+ void *aux[NSV_MAX_AUXSTREAMS];
+ int aux_len[NSV_MAX_AUXSTREAMS];
+ unsigned int aux_types[NSV_MAX_AUXSTREAMS];
+ int is_sync_frame;
+ void *audio;
+ int audio_len;
+ void *video;
+ int video_len;
+};
+
+
+/* nsv_Unpacketer is used to unpacket a bitstream into audio/video/auxiliary data
+ * to decode, use an nsv_InBS object with data, and call unpacket().
+ * ex:
+ * nsv_Unpacketer up;
+ * nsv_InBS in;
+ * nsv_InBS videoout, audioout;
+ * up.setVideoOut(&videoout);
+ * up.setAudioOut(&audioout);
+ * for (;;) {
+ * int ret=up.unpacket(in);
+ * if (ret < 0) break; // eof
+ * if (ret > 0) add_data_to_bitstream(&in,ret);
+ * if (!ret) { // got frame
+ * int vl=videoout.getbits(32);
+ * int al=videoout.getbits(32);
+ * char *vd=(char*)videoout.getcurbyteptr();
+ * char *ad=(char*)audioout.getcurbyteptr();
+ * doDecode(vd,vl,ad,al);
+ * videoout.seek(vl*8);
+ * audioout.seek(al*8);
+ * videoout.compact(); // free memory up
+ * audioout.compact(); // free memory up
+ * in.compact(); // free memory up
+ * }
+ * }
+ */
+
+class nsv_Unpacketer {
+ public:
+ nsv_Unpacketer() { reset(); }
+ ~nsv_Unpacketer() { }
+
+ void reset(int full=1); // if full, full reset is done.
+ // if not, then it is a partial reset (ie for seeking)
+
+ // when EOF is set, the unpacketer will fail instead of requesting more data at the
+ // end; it will also not require that the next frame be available for sync
+ // (normally it looks ahead to verify data)
+ void setEof(int eof=1) { m_eof=eof; }
+ int getEof() { return m_eof; }
+
+ // use these to set where the unpacketer writes the output of each stream
+ // set to NULL to ignore output of that stream
+
+ void setAudioOut(nsv_InBS *output=NULL) { m_audiobs=output; }
+ // the format of the audio data written to the output is:
+ // 32 bits: length of frame
+ // ? bytes: audio data
+ // (to read):
+ // int l=output->getbits(32);
+ // decode_audio(output->getcurbyteptr(),l);
+ // output->seek(l*8);
+
+
+ void setVideoOut(nsv_InBS *output=NULL) { m_videobs=output; }
+ // the format of the video data written to the output is:
+ // 32 bits: length of frame
+ // ? bytes: video data
+ // (to read):
+ // int l=output->getbits(32);
+ // decode_video(output->getcurbyteptr(),l);
+ // output->seek(l*8);
+
+ void setAuxOut(nsv_InBS *output=NULL) { m_auxbs=output; }
+ // the format of the aux data written to the output is:
+ // 32 bits: length of frame
+ // 32 bits: type of aux data
+ // ? bytes: aux data
+ // (to read):
+ // int l=output->getbits(32);
+ // int type=output->getbits(32);
+ // decode_aux(output->getcurbyteptr(),l);
+ // output->seek(l*8);
+ // aux is different than audio/video in that it includes a 32 bit
+ // type value that is not included in the length.
+
+
+ // returns 0 on success, >0 on needs (at least X bytes) more data,
+ // -1 on error (eof and no header found)
+ int unpacket(nsv_InBS &bs);
+
+
+ // do we have enough sync to determine formats/widths/heights/framerates
+ int isValid() { return valid; }
+
+ // are we fully synched?
+ int isSynched() { return synched; }
+
+ // get sync offset from when we first synched up
+ signed int getSyncOffset() { return (signed int) syncoffset; }
+
+ // get sync offset from current frame (not usually used)
+ signed int getCurSyncOffset() { return (signed int) syncoffset_cur; }
+
+ // get video, audio, width, height, framerate formats.
+ unsigned int getVidFmt() { return vidfmt; }
+ unsigned int getAudFmt() { return audfmt; }
+ unsigned int getWidth() { return width; }
+ unsigned int getHeight() { return height; }
+ double getFrameRate() { return framerate; }
+ unsigned char getFrameRateIdx() { return framerate_idx; }
+
+ // is current frame a sync frame?
+ int isSynchFrame() { return is_sync_frame; }
+
+ private:
+ nsv_InBS *m_audiobs, *m_videobs, *m_auxbs;
+ int valid; // contents of stream info are valid for syncing
+ int synched; // turns off anal packet checking
+ unsigned int vidfmt;
+ unsigned int audfmt;
+ unsigned int width;
+ unsigned int height;
+ double framerate;
+ int is_sync_frame;
+ unsigned char framerate_idx;
+ int syncoffset;
+ int syncoffset_cur;
+
+ int m_eof;
+};
+
+
+/*********************************************************************
+** NSV file header reading/writing functions
+*/
+
+
+typedef struct {
+ // header_size is the size of NSV header. nsv_writeheader() and nsv_readheader()
+ // will set this automatically
+ unsigned int header_size;
+
+ // file_lenbytes is the size of the NSV bitstream (not including the header size)
+ // this can be 0xFFFFFFFF to signify unknown length
+ unsigned int file_lenbytes;
+
+ // file_lenms is the length of the NSV bitstream in milliseconds.
+ // this can be 0xFFFFFFFF to signify unknown length
+ unsigned int file_lenms;
+
+ // metadata_len describes the length of the metadata.
+ unsigned int metadata_len;
+
+ // toc_alloc describes the allocated length of the TOC (in entries).
+ // set this to zero to use toc_size (recommended).
+ unsigned int toc_alloc;
+
+ // toc_size describes the used size of the TOC (in entries)
+ // set this to zero to disable the TOC. When using toc_ex,
+ // this must be < toc_alloc/2 (if using nsv_writeheader, and
+ // toc_size is too big, toc_alloc will be grown automatically.
+ unsigned int toc_size;
+
+ // buffer which contains the TOC. this will be automatically
+ // allocated when using nsv_readheader(), but you should allocate
+ // this yourself when using nsv_writeheader()
+ unsigned int *toc;
+
+ // if used, contains time pairs (in frames) for the offset. this will be
+ // automatically allocated when using nsv_readheader(), but you should allocate
+ // this yourself when using nsv_writeheader()
+ // DO NOT FREE THIS VALUE IF IT WAS ALLOCATED FROM NSV_READHEADER. :)
+ // (it is just an extension of toc, which should be freed with free())
+ unsigned int *toc_ex;
+
+ // buffer which contains metadata. allocated when using nsv_readheader(),
+ // but you should allocate this yourself when using nsv_writeheader()
+ // note that nsv_readheader() will NULL terminate this buffer.
+ void *metadata;
+
+} nsv_fileHeader;
+
+// nsv_writeheader() writes the NSV file header to the bitstream bs.
+// the NSV file header will be at LEAST padto bytes long (usually
+// you will leave padto to 0)
+void nsv_writeheader(nsv_OutBS &bs, nsv_fileHeader *hdr, unsigned int padto);
+
+// nsv_readheader() reads an NSV file header from a bitstream bs.
+// if the return value is less than zero, then there is no NSV
+// file header in bs. if the return value is zero, the NSV file
+// header was succesfully read. if the return value is positive,
+// then at least that many more bytes are needed to decode the
+// header.
+// ex:
+// nsv_InBS bs;
+// nsv_fileHeader hdr;
+// for (;;) {
+// int ret=nsv_readheader(bs,&hdr);
+// if (ret<=0) break;
+// addBytesToBs(bs,ret);
+// }
+// if (hdr.header_size) { we_got_valid_header(&hdr); }
+//
+
+int nsv_readheader(nsv_InBS &bs, nsv_fileHeader *hdr);
+
+
+// nsv_getmetadata() retrieves a metadata item from the metadata
+// block. if that item is not found, NULL is returned.
+// Note that the value returned by nsv_getmetadata() has been
+// malloc()'d, and you must free() it when you are done.
+// ex:
+// char *v=nsv_getmetadata(hdr.metadata,"TITLE");
+// if (v) printf("title=%s\n",v);
+// free(v);
+//
+
+char *nsv_getmetadata(void *metadata, char *name);
+
+
+#endif//_NSVLIB_H_