changeset 14753:70c446099f40

new mpeg muxer compatible with dvd/[s]vcd; small changes in the muxer layer (sanity checks in the muxer_init functions)
author nicodvb
date Mon, 21 Feb 2005 21:45:49 +0000
parents eddd61a68410
children 57541bc7b796
files cfg-mencoder.h libmpdemux/muxer.c libmpdemux/muxer.h libmpdemux/muxer_avi.c libmpdemux/muxer_mpeg.c libmpdemux/muxer_rawvideo.c
diffstat 6 files changed, 2363 insertions(+), 351 deletions(-) [+]
line wrap: on
line diff
--- a/cfg-mencoder.h	Mon Feb 21 17:40:46 2005 +0000
+++ b/cfg-mencoder.h	Mon Feb 21 21:45:49 2005 +0000
@@ -72,6 +72,7 @@
 #endif
 
 extern m_option_t nuvopts_conf[];
+extern m_option_t mpegopts_conf[];
 
 m_option_t ovc_conf[]={
 	{"copy", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_COPY, NULL},
@@ -269,6 +270,7 @@
 #endif
 
 	{"nuvopts",  nuvopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+	{"mpegopts",  mpegopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
 
 #define MAIN_CONF
 #include "cfg-common.h"
--- a/libmpdemux/muxer.c	Mon Feb 21 17:40:46 2005 +0000
+++ b/libmpdemux/muxer.c	Mon Feb 21 21:45:49 2005 +0000
@@ -12,6 +12,11 @@
 #include "ms_hdr.h"
 
 #include "muxer.h"
+#include "stream.h"
+#include "demuxer.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+#include "stheader.h"
 
 muxer_t *muxer_new_muxer(int type,FILE *f){
     muxer_t* muxer=malloc(sizeof(muxer_t));
@@ -19,14 +24,17 @@
     muxer->file = f;
     switch (type) {
       case MUXER_TYPE_MPEG:
-	muxer_init_muxer_mpeg(muxer);
+	if(! muxer_init_muxer_mpeg(muxer))
+	  return NULL;
 	break;
       case MUXER_TYPE_RAWVIDEO:
-        muxer_init_muxer_rawvideo(muxer);
+        if(! muxer_init_muxer_rawvideo(muxer))
+	  return NULL;
 	break;
       case MUXER_TYPE_AVI:
       default:
-	muxer_init_muxer_avi(muxer);
+	if(! muxer_init_muxer_avi(muxer))
+	  return NULL;
     }
     return muxer;
 }
--- a/libmpdemux/muxer.h	Mon Feb 21 17:40:46 2005 +0000
+++ b/libmpdemux/muxer.h	Mon Feb 21 21:45:49 2005 +0000
@@ -8,7 +8,6 @@
 #define MUXER_TYPE_MPEG 1
 #define MUXER_TYPE_RAWVIDEO 2
 
-#define MUXER_MPEG_BLOCKSIZE 2048	// 2048 or 2324 - ?
 
 typedef struct {
   // muxer data:
@@ -24,7 +23,9 @@
   unsigned int buffer_len;
   // mpeg block buffer:
   unsigned char *b_buffer;
-  unsigned int b_buffer_ptr;
+  unsigned int b_buffer_size;	//size of b_buffer
+  unsigned int b_buffer_ptr;	//index to next data to write
+  unsigned int b_buffer_len;	//len of next data to write
   // source stream:
   void* source; // sh_audio or sh_video
   int codec; // codec used for encoding. 0 means copy
@@ -58,23 +59,27 @@
   int idx_size;
   // streams:
   int num_videos;	// for MPEG recalculations
+  int num_audios;
   unsigned int sysrate;	// max rate in bytes/s
   //int num_streams;
   muxer_stream_t* def_v;  // default video stream (for general headers)
   muxer_stream_t* streams[MUXER_MAX_STREAMS];
+  void (*fix_stream_parameters)(muxer_stream_t *);
   void (*cont_write_chunk)(muxer_stream_t *,size_t,unsigned int);
   void (*cont_write_header)(struct muxer_t *);
   void (*cont_write_index)(struct muxer_t *);
   muxer_stream_t* (*cont_new_stream)(struct muxer_t *,int);
   FILE* file;
+  void *priv;
 } muxer_t;
 
 muxer_t *muxer_new_muxer(int type,FILE *);
 #define muxer_new_stream(muxer,a) muxer->cont_new_stream(muxer,a)
+#define muxer_stream_fix_parameters(muxer, a) muxer->fix_stream_parameters(a)
 #define muxer_write_chunk(a,b,c) a->muxer->cont_write_chunk(a,b,c)
 #define muxer_write_header(muxer) muxer->cont_write_header(muxer)
 #define muxer_write_index(muxer) muxer->cont_write_index(muxer)
 
-void muxer_init_muxer_avi(muxer_t *);
-void muxer_init_muxer_mpeg(muxer_t *);
-void muxer_init_muxer_rawvideo(muxer_t *);
+int muxer_init_muxer_avi(muxer_t *);
+int muxer_init_muxer_mpeg(muxer_t *);
+int muxer_init_muxer_rawvideo(muxer_t *);
--- a/libmpdemux/muxer_avi.c	Mon Feb 21 17:40:46 2005 +0000
+++ b/libmpdemux/muxer_avi.c	Mon Feb 21 21:45:49 2005 +0000
@@ -660,9 +660,10 @@
   }
 }
 
-void muxer_init_muxer_avi(muxer_t *muxer){
+int muxer_init_muxer_avi(muxer_t *muxer){
   muxer->cont_new_stream = &avifile_new_stream;
   muxer->cont_write_chunk = &avifile_write_chunk;
   muxer->cont_write_header = &avifile_write_header;
   muxer->cont_write_index = &avifile_write_index;
+  return 1;
 }
--- a/libmpdemux/muxer_mpeg.c	Mon Feb 21 17:40:46 2005 +0000
+++ b/libmpdemux/muxer_mpeg.c	Mon Feb 21 21:45:49 2005 +0000
@@ -14,68 +14,411 @@
 #include "ms_hdr.h"
 
 #include "muxer.h"
+#include "stream.h"
+#include "demuxer.h"
+#include "stheader.h"
+#include "../m_option.h"
+#include "mpeg_hdr.h"
 
-// 18 bytes reserved for block headers and STD
-#define MUXER_MPEG_DATASIZE (MUXER_MPEG_BLOCKSIZE-18)
+#define PACK_HEADER_START_CODE 0x01ba
+#define SYSTEM_HEADER_START_CODE 0x01bb
+#define PSM_START_CODE 0x01bc
+
+#define PES_PRIVATE1 0x01bd
+#define PES_PRIVATE2 0x01bf
+
+#define MUX_MPEG1 1
+#define MUX_MPEG2 2
+
+#define VIDEO_MPEG1 0x10000001
+#define VIDEO_MPEG2 0x10000002
+#define AUDIO_MP2 0x50
+#define AUDIO_MP3 0x55
+#define AUDIO_A52 0x2000
+#define AUDIO_LPCM 0x10001	/* only a placeholder at the moment */
+
+#define ASPECT_1_1 1
+#define ASPECT_4_3 2
+#define ASPECT_16_9 3
+#define ASPECT_2_21_1 4
+
+#define FRAMERATE_23976 1
+#define FRAMERATE_24 2
+#define FRAMERATE_25 3
+#define FRAMERATE_2997 4
+#define FRAMERATE_30 5
+#define FRAMERATE_50 6
+#define FRAMERATE_5994 7
+#define FRAMERATE_60 8
+
+static char ftypes[] = {'?', 'I', 'P', 'B'}; 
+#define FTYPE(x) (ftypes[(x)])
+
+
+static const char *framerates[] = {
+	"unchanged", "23.976", "24", "25", "29.97", "30", "50", "59.94", "60"
+};
+
+static const char *aspect_ratios[] = {
+	"unchanged", "1/1", "4/3", "16/9", "2.21/1"
+};
+
+static char *conf_mux = "mpeg2";
+static uint16_t conf_packet_size = 0;		//dvd
+static uint32_t conf_muxrate = 0;		//kb/s
+static char *conf_vaspect = NULL, *conf_vframerate = NULL;
+static uint32_t conf_vwidth = 0, conf_vheight = 0, conf_panscan_width = 0, conf_panscan_height = 0;
+static uint32_t conf_vbitrate = 0;
+static int conf_init_vpts = 200, conf_init_apts = 200;
+static int conf_ts_allframes = 0;
+static int conf_init_adelay = 0;
+static int conf_drop = 0;
+static int conf_skip_padding = 0;
+static int conf_noreorder = 0;
+
+enum FRAME_TYPE {
+	I_FRAME = 1,
+	P_FRAME = 2,
+	B_FRAME = 3
+};
 
-// ISO-11172 requirements
-#define MPEG_MAX_PTS_DELAY 90000 /* 1s */
-#define MPEG_MAX_SCR_INTERVAL 63000 /* 0.7s */
+typedef struct {
+	uint8_t *buffer;
+	size_t size;
+	size_t alloc_size;
+	uint8_t type;
+	uint32_t temp_ref;
+	uint64_t pts, dts, idur;
+} mpeg_frame_t;
+
+typedef struct {
+	uint8_t cnt;		// how many entries we use
+	struct {
+		uint8_t id, type;
+		uint32_t bufsize;
+		uint32_t format;
+	} streams[50];		//16 video + 16 audio mpa + 16 audio private + bd/bf for dvd
+} sys_info_t;
+
+typedef struct {
+	uint8_t cnt;		// how many entries we use
+	struct {
+		uint8_t id;
+		uint8_t type;
+		uint32_t format;
+	} streams[50];		//16 video + 16 audio mpa + 16 audio private + bd/bf for dvd
+} psm_info_t;
+
+
+typedef struct {
+	int mux;
+	sys_info_t sys_info;
+	psm_info_t psm_info;
+	uint16_t packet_size;
+	int is_dvd, is_xvcd, is_xsvcd, is_genmpeg1, is_genmpeg2, ts_allframes, has_video, has_audio;
+	int skip_padding;
+	int update_system_header, use_psm;
+	off_t headers_size, data_size;
+	uint64_t scr, vbytes, abytes, init_delay_pts;
+	uint32_t muxrate;
+	uint8_t *buff, *tmp, *residual;
+	uint32_t residual_cnt, headers_cnt;
+	double init_adelay;
+	int drop;
+	
+	//video patching parameters
+	uint8_t vaspect, vframerate;
+	uint16_t vwidth, vheight, panscan_width, panscan_height;
+	uint32_t vbitrate;
+	int patch_seq, patch_sde;
+	int psm_streams_cnt;
+} muxer_priv_t;
+
+
+typedef struct {
+	int has_pts, has_dts, pes_is_aligned, type, is_late, min_pes_hlen, psm_fixed;
+	uint64_t pts, last_pts, last_dts, dts, init_pts, init_dts, size, frame_duration, delta_pts, nom_delta_pts, frame_size, last_saved_pts;
+	uint32_t buffer_size;
+	uint8_t pes_priv_headers[4], has_pes_priv_headers;	//for A52 and LPCM
+	uint32_t bitrate, rest;
+	int32_t compensate;
+	double delta_clock, timer, aframe_delta_pts, last_dpts;
+	mpeg_frame_t *framebuf;
+	uint16_t framebuf_cnt;
+	uint16_t framebuf_used;
+	uint16_t max_pl_size;
+	int32_t last_tr;
+	uint32_t max_tr;
+	uint8_t id, reorder, is_mpeg12;
+	mp_mpeg_header_t picture;
+} muxer_headers_t;
+
 
-// suggestions
-#define MPEG_STARTPTS 45000 /* 0.5s */
-#define MPEG_MIN_PTS_DELAY 9000 /* 0.1s */
-#define MPEG_STARTSCR 9 /* 0.1ms */
+m_option_t mpegopts_conf[] = {
+	{"format", &(conf_mux), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+	{"size", &(conf_packet_size), CONF_TYPE_INT, CONF_RANGE, 0, 65535, NULL},
+	{"muxrate", &(conf_muxrate), CONF_TYPE_INT, CONF_RANGE, 0, 12000000, NULL},	//12 Mb/s
+	{"vaspect", &(conf_vaspect), CONF_TYPE_STRING, 0, 0, 0, NULL},
+	{"vframerate", &(conf_vframerate), CONF_TYPE_STRING, 0, 0, 0, NULL},
+	{"vwidth", &(conf_vwidth), CONF_TYPE_INT, CONF_RANGE, 1, 4095, NULL},
+	{"vheight", &(conf_vheight), CONF_TYPE_INT, CONF_RANGE, 1, 4095, NULL},
+	{"vpswidth", &(conf_panscan_width), CONF_TYPE_INT, CONF_RANGE, 1, 16383, NULL},
+	{"vpsheight", &(conf_panscan_height), CONF_TYPE_INT, CONF_RANGE, 1, 16383, NULL},
+	{"vbitrate", &(conf_vbitrate), CONF_TYPE_INT, CONF_RANGE, 1, 104857599, NULL},
+	{"init_vpts", &(conf_init_vpts), CONF_TYPE_INT, CONF_RANGE, 100, 700, NULL},		//2*frametime at 60fps
+	{"init_apts", &(conf_init_apts), CONF_TYPE_INT, CONF_RANGE, 100, 700, NULL},
+	{"init_adelay", &conf_init_adelay, CONF_TYPE_INT, CONF_RANGE, -32760, -1, NULL},
+	{"drop", &conf_drop, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"tsaf", &conf_ts_allframes, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"skip_padding", &conf_skip_padding, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"noreorder", &conf_noreorder, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+static void fix_audio_sys_header(muxer_priv_t *priv, uint8_t id, uint8_t newid, uint32_t size)
+{
+	uint8_t i;
+	
+	for(i = 0; i < priv->sys_info.cnt; i++)
+	{
+		if(priv->sys_info.streams[i].id == id)
+		{
+			priv->sys_info.streams[i].id = newid;
+			priv->sys_info.streams[i].type = 1;
+			priv->sys_info.streams[i].bufsize = size;
+		}
+	}
+}
+
+static void fix_buffer_params(muxer_priv_t *priv, uint8_t id, uint32_t size)
+{
+	uint8_t i;
+	
+	for(i = 0; i < priv->sys_info.cnt; i++)
+		if(priv->sys_info.streams[i].id == id)
+			priv->sys_info.streams[i].bufsize = size;
+}
+
+static inline int is_mpeg1(uint32_t x)
+{
+	return (
+		(x == 0x10000001) ||
+		(x == mmioFOURCC('m','p','g','1')) ||
+		(x == mmioFOURCC('M','P','G','1'))
+	);
+}
+
+static inline int is_mpeg2(uint32_t x)
+{
+	return (
+		(x == 0x10000002) ||
+		(x == mmioFOURCC('m','p','g','2')) ||
+		(x == mmioFOURCC('M','P','G','2')) ||
+		(x == mmioFOURCC('m','p','e','g')) ||
+		(x == mmioFOURCC('M','P','E','G'))
+	);
+}
 
-//static unsigned int mpeg_min_delay;
-//static unsigned int mpeg_max_delay;
+static inline int is_mpeg4(uint32_t x)
+{
+	return (
+		(x == 0x10000004) ||
+		(x == mmioFOURCC('d','i','v','x')) ||
+		(x == mmioFOURCC('D','I','V','X')) ||
+		(x == mmioFOURCC('x','v','i','d')) ||
+		(x == mmioFOURCC('X','V','I','D')) ||
+		(x == mmioFOURCC('X','v','i','D')) ||
+		(x == mmioFOURCC('x','v','i','x')) ||
+		(x == mmioFOURCC('X','V','I','X')) ||
+		(x == mmioFOURCC('m','p','4','v')) ||
+		(x == mmioFOURCC('M','P','4','V'))
+	);
+}
+
+//from unrarlib.c
+static uint32_t CalcCRC32(uint8_t *buff, uint32_t size)
+{
+	uint32_t i, j, CRCTab[256], crc;
+	
+	for(i = 0;i < 256; i++)
+	{
+		for(crc = i, j = 0; j < 8; j++)
+			crc= (crc & 1) ? (crc >> 1)^0xEDB88320L : (crc >> 1);
+		CRCTab[i] = crc;
+	}
+
+	
+	crc = 0xffffffff;
+	for(i = 0; i < size; i++)
+		crc = (crc << 8) ^ CRCTab[((crc >> 24) ^ buff[i]) & 0xff];
+	
+	return crc;
+}
+
+
+static void add_to_psm(muxer_priv_t *priv, uint8_t id, uint32_t format)
+{
+	uint8_t i;
+	
+	i = priv->psm_info.cnt;
+	priv->psm_info.streams[i].id = id;
+	priv->psm_info.streams[i].format = format;
+	
+	if(is_mpeg1(format))
+		priv->psm_info.streams[i].type = 0x01;
+	else if(is_mpeg2(format))
+		priv->psm_info.streams[i].type = 0x02;
+	else if(is_mpeg4(format))
+		priv->psm_info.streams[i].type = 0x10;
+	else if(format == AUDIO_MP2 || format == AUDIO_MP3)
+		priv->psm_info.streams[i].type = 0x03;
+	else
+		priv->psm_info.streams[i].type = 0x81;
+	
+	if(format == AUDIO_A52)
+		memcpy((char*) &(priv->psm_info.streams[i].format), "AC-3", 4);
+	
+	priv->psm_info.cnt++;
+}
+
+
+static mpeg_frame_t *init_frames(uint16_t num, size_t size)
+{
+	mpeg_frame_t *tmp;
+	uint16_t i;
+	
+	tmp = (mpeg_frame_t *) calloc(num, sizeof(mpeg_frame_t));
+	if(tmp == NULL)
+		return NULL;
+		
+	for(i=0; i < num; i++)
+	{
+		tmp[i].buffer = (uint8_t *) calloc(1, size);
+		if(tmp[i].buffer == NULL)
+			return NULL;
+		tmp[i].size = 0;
+		tmp[i].alloc_size = size;
+		tmp[i].pts = 0;
+	}
+	
+	return tmp;
+}
+
+static uint32_t calc_pack_hlen(muxer_priv_t *priv, muxer_headers_t *h);
 
 static muxer_stream_t* mpegfile_new_stream(muxer_t *muxer,int type){
+  muxer_priv_t *priv = (muxer_priv_t*) muxer->priv;
   muxer_stream_t *s;
+  muxer_headers_t *spriv;
 
   if (!muxer) return NULL;
   if(muxer->avih.dwStreams>=MUXER_MAX_STREAMS){
-    printf("Too many streams! increase MUXER_MAX_STREAMS !\n");
+    mp_msg(MSGT_MUXER, MSGL_ERR, "Too many streams! increase MUXER_MAX_STREAMS !\n");
     return NULL;
   }
   switch (type) {
     case MUXER_TYPE_VIDEO:
-      if (muxer->num_videos >= 15) {
-	printf ("MPEG stream can't contain above of 15 video streams!\n");
+      if (muxer->num_videos >= 16) {
+	mp_msg(MSGT_MUXER, MSGL_ERR, "MPEG files can't contain more than 16 video streams!\n");
 	return NULL;
       }
       break;
     case MUXER_TYPE_AUDIO:
-      if (muxer->avih.dwStreams - muxer->num_videos >= 31) {
-	printf ("MPEG stream can't contain above of 31 audio streams!\n");
+      if (muxer->num_audios >= 16) {
+	mp_msg(MSGT_MUXER, MSGL_ERR, "MPEG files can't contain more than 16 audio streams!\n");
 	return NULL;
       }
       break;
     default:
-      printf ("Unknown stream type!\n");
+      mp_msg(MSGT_MUXER, MSGL_ERR, "Unknown stream type!\n");
       return NULL;
   }
-  s=malloc(sizeof(muxer_stream_t));
-  memset(s,0,sizeof(muxer_stream_t));
+  s = (muxer_stream_t*) calloc(1, sizeof(muxer_stream_t));
   if(!s) return NULL; // no mem!?
-  if (!(s->b_buffer = malloc (MUXER_MPEG_BLOCKSIZE))) {
+  if (!(s->b_buffer = malloc(priv->packet_size))) {
     free (s);
     return NULL; // no mem?!
   }
+  s->b_buffer_size = priv->packet_size;
+  s->b_buffer_ptr = 0;
+  s->b_buffer_len = 0;
+  s->priv = (muxer_headers_t*) calloc(1, sizeof(muxer_headers_t));
+  if(s->priv == NULL) {
+    free(s);
+    return NULL;
+  }
+  spriv = (muxer_headers_t *) s->priv;
   muxer->streams[muxer->avih.dwStreams]=s;
   s->type=type;
   s->id=muxer->avih.dwStreams;
-  s->timer=0.0;
-  s->size=0;
   s->muxer=muxer;
+  
   if (type == MUXER_TYPE_VIDEO) {
-    s->ckid = be2me_32 (0x1e0 + muxer->num_videos);
+    spriv->type = 1;
+    spriv->init_dts = 0;
+    spriv->init_pts = conf_init_vpts * 90 * 1024;
+    spriv->last_pts = spriv->init_pts;
+    spriv->last_saved_pts = 0;
+    spriv->init_dts = spriv->last_dts = spriv->init_pts;
+    spriv->pts = spriv->dts = 0;
+    spriv->last_dpts = spriv->timer;
+    spriv->delta_pts = spriv->nom_delta_pts = 0;
+    spriv->id = 0xe0 + muxer->num_videos;
+    s->ckid = be2me_32 (0x100 + spriv->id);
+    if(priv->is_genmpeg1 || priv->is_genmpeg2) {
+      int n = priv->sys_info.cnt;
+      
+      priv->sys_info.streams[n].id = spriv->id;
+      priv->sys_info.streams[n].type = 1;
+      priv->sys_info.streams[n].bufsize = (s->h.dwSuggestedBufferSize > 0 ? s->h.dwSuggestedBufferSize : 46*1024);
+      priv->sys_info.cnt++;
+    }
     muxer->num_videos++;
+    priv->has_video++;
     s->h.fccType=streamtypeVIDEO;
     if(!muxer->def_v) muxer->def_v=s;
+    spriv->framebuf_cnt = 30;
+    spriv->framebuf_used = 0;
+    spriv->framebuf = init_frames(spriv->framebuf_cnt, (size_t) 5000);
+    bzero(&(spriv->picture), sizeof(spriv->picture));
+    if(spriv->framebuf == NULL) {
+      mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't allocate initial frames structure, abort!\n");
+      return NULL;
+    }
+    if(priv->is_xvcd)
+      spriv->min_pes_hlen = 18;
+    else if(priv->is_xsvcd)
+      spriv->min_pes_hlen = 22;
+    if(conf_noreorder)
+      spriv->reorder = 0;
+    else
+      spriv->reorder = 1;
     mp_msg (MSGT_MUXER, MSGL_DBG2, "Added video stream %d, ckid=%X\n", muxer->num_videos, s->ckid);
   } else { // MUXER_TYPE_AUDIO
-    s->ckid = be2me_32 (0x1c0 + s->id - muxer->num_videos);
+    spriv->type = 0;
+    spriv->pts = 1;
+    spriv->dts = 0;
+    spriv->max_pl_size = priv->packet_size - calc_pack_hlen(priv, spriv);
+    spriv->init_pts = conf_init_apts * 90 * 1024;
+    spriv->pts = spriv->init_pts;
+    spriv->dts = 0;
+    spriv->id = 0xc0 + muxer->num_audios;
+    s->ckid = be2me_32 (0x100 + spriv->id);
+    if(priv->is_genmpeg1 || priv->is_genmpeg2) {
+      int n = priv->sys_info.cnt;
+      
+      priv->sys_info.streams[n].id = spriv->id;
+      priv->sys_info.streams[n].type = 0;
+      priv->sys_info.streams[n].bufsize = (s->h.dwSuggestedBufferSize > 0 ? s->h.dwSuggestedBufferSize : 4*1024);
+      priv->sys_info.cnt++;
+    }
+    if(priv->is_xvcd)
+      spriv->min_pes_hlen = 13;
+    else if(priv->is_xsvcd)
+      spriv->min_pes_hlen = 17;
+    
+    muxer->num_audios++;
+    priv->has_audio++;
     s->h.fccType=streamtypeAUDIO;
     mp_msg (MSGT_MUXER, MSGL_DBG2, "Added audio stream %d, ckid=%X\n", s->id - muxer->num_videos + 1, s->ckid);
   }
@@ -83,364 +426,2016 @@
   return s;
 }
 
-static void write_mpeg_ts(unsigned char *b, unsigned int ts, char mod) {
-  b[0] = ((ts >> 29) & 0xf) | 1 | mod;
+static void write_mpeg_ts(unsigned char *b, uint64_t ts, uint8_t mod) {
+  ts >>= 10;
+  b[0] = mod | ((ts >> 29) & 0xf) | 1;
   b[1] = (ts >> 22) & 0xff;
   b[2] = ((ts >> 14) & 0xff) | 1;
   b[3] = (ts >> 7) & 0xff;
   b[4] = ((ts << 1) & 0xff) | 1;
 }
 
-static void write_mpeg_rate(unsigned char *b, unsigned int rate) {
-  if (rate)
-    rate--; // for round upward
-  rate /= 50;
-  rate++; // round upward
-  b[0] = ((rate >> 15) & 0x7f) | 0x80;
-  b[1] = (rate >> 7) & 0xff;
-  b[2] = ((rate << 1) & 0xff) | 1;
+
+static void write_mpeg_rate(int type, unsigned char *b, unsigned int rate) 
+{
+	rate = (rate+49) / 50;
+	
+	if(type == MUX_MPEG1)
+	{
+		b[0] = ((rate >> 15) & 0x7f) | 0x80;
+		b[1] = (rate >> 7) & 0xff;
+		b[2] = ((rate << 1) & 0xff) | 1;
+	}
+	else
+	{
+		b[0] = (rate >> 14);
+		b[1] = (rate >> 6) & 0xff;
+		b[2] = ((rate & 0x3f) << 2) | 0x03;	
+	}
+}
+
+
+static void write_mpeg_std(unsigned char *b, unsigned int size, unsigned int type, uint8_t mod) 
+{
+	//type = 0:mpeg audio/128, 1:video and pes private streams (including ac3/dts/lpcm)/1024
+	if(type == 0)	//audio
+		size = (size + 127) / 128;
+	else		//video or other
+		size = ((size + 1023) / 1024);
+
+	if(! size)
+		size++;
+
+	b[0] = ((size >> 8) & 0x3f) | (type==1 ? 0x60 : 0x40) | mod;
+	b[1] = size & 0xff;
+}
+
+static void write_mpeg2_scr(unsigned char *b, uint64_t ts) 
+{
+	uint16_t t1, t2, t3;
+	ts >>= 10;
+	ts &= 0x1FFFFFFFFULL;	//33 bits, no extension; input must be * 92160000
+	t1 = (ts >> 30) & 0x7;;
+	t2 = (ts >> 15) & 0x7fff;
+	t3 = ts & 0x7fff;
+	
+	b[0] = (t1 << 3 ) | 0x44 | ((t2 >> 13) & 0x3);
+	b[1] = (t2 >> 5);
+	b[2] = (t2 & 0x1f) << 3 | 0x4 | ((t3 >> 13) & 0x3);
+	b[3] = (t3 >> 5);
+	b[4] = (t3 & 0x1f) << 3 | 0x4;
+	b[5] = 1;
+}
+
+
+static int write_mpeg_pack_header(muxer_t *muxer, char *buff)
+{
+	int len;
+	muxer_priv_t *priv;
+	
+	priv = (muxer_priv_t *) muxer->priv;
+	*(uint32_t *)buff = be2me_32(PACK_HEADER_START_CODE);
+	if(priv->mux==MUX_MPEG1)
+	{
+		write_mpeg_ts(&buff[4], priv->scr, 0x20); // 0010 and SCR
+		write_mpeg_rate(priv->mux, &buff[9], muxer->sysrate);
+		len = 12;
+	}
+	else
+	{
+		write_mpeg2_scr(&buff[4], priv->scr); // 0010 and SCR
+		write_mpeg_rate(priv->mux, &buff[10], muxer->sysrate);
+		buff[13] = 0xf8; //5 bits reserved + 3 set to 0 to indicate 0 stuffing bytes 
+		len = 14;
+	}
+
+	return len;
+}
+
+
+static int write_mpeg_system_header(muxer_t *muxer, char *buff)
+{
+	int len;
+	uint8_t i;
+	muxer_priv_t *priv;
+	priv = (muxer_priv_t *) muxer->priv;
+	
+	len = 0;
+	*(uint32_t *)(&buff[len]) = be2me_32(SYSTEM_HEADER_START_CODE);
+	len += 4;
+	*(uint16_t *)(&buff[len]) = 0; 	//fake length, we'll fix it later
+	len += 2;
+	write_mpeg_rate(MUX_MPEG1, &buff[len], muxer->sysrate);
+	len += 3;
+		
+	buff[len++] = 0x4 | (priv->is_xvcd ? 1 : 0); 	//1 audio stream bound, no fixed, CSPS only for xvcd
+	buff[len++] = 0xe1;	//system_audio_lock, system_video_lock, marker, 1 video stream bound
+	
+	buff[len++] = ((priv->mux == MUX_MPEG1) ? 0xff : 0x7f);	//in mpeg2 there's the packet rate restriction
+	
+	for(i = 0; i < priv->sys_info.cnt; i++)
+	{
+		buff[len++] = priv->sys_info.streams[i].id;
+		write_mpeg_std(&buff[len], priv->sys_info.streams[i].bufsize, priv->sys_info.streams[i].type, 
+			(priv->sys_info.streams[i].type == 1 ? 0xe0: 0xc0));
+		len += 2;
+	}
+	
+	*(uint16_t *)(&buff[4]) = be2me_16(len - 6);	// length field fixed
+	
+	return len;
+}
+
+static int write_mpeg_psm(muxer_t *muxer, char *buff)
+{
+	int len;
+	uint8_t i;
+	uint16_t dlen;
+	muxer_priv_t *priv;
+	priv = (muxer_priv_t *) muxer->priv;
+	
+	len = 0;
+	*(uint32_t *)(&buff[len]) = be2me_32(PSM_START_CODE);
+	len += 4;
+	*(uint16_t *)(&buff[len]) = 0; 	//fake length, we'll fix it later
+	len += 2;
+	buff[len++] = 0xe0;		//1 current, 2 bits reserved, 5 version 0
+	buff[len++] = 0xff;		//7 reserved, 1 marker
+	buff[len] = buff[len+1] = 0;	//length  of the program descriptors (unused)
+	len += 2;
+	*(uint16_t *)(&buff[len]) = 0; //length of the es descriptors
+	len += 2;
+	
+	dlen = 0;
+	for(i = 0; i < priv->psm_info.cnt; i++)
+	{
+		if(
+			(priv->psm_info.streams[i].id == 0xbd) || 
+			(priv->psm_info.streams[i].id >= 0xe0 && priv->psm_info.streams[i].id <= 0xef) || 
+			(priv->psm_info.streams[i].id >= 0xc0 && priv->psm_info.streams[i].id <= 0xcf)
+		)
+		{
+			buff[len++] = priv->psm_info.streams[i].type;
+			buff[len++] = priv->psm_info.streams[i].id;
+			buff[len++] = 0;	//len of descriptor upper ...
+			buff[len++] = 6;	//... lower
+			
+			//registration descriptor
+			buff[len++] = 0x5;	//tag
+			buff[len++] = 4;	//length: 4 bytes
+			memcpy(&(buff[len]), (char*) &(priv->psm_info.streams[i].format), 4);
+			len += 4;
+			dlen += 10;
+		}
+	}
+	*(uint16_t *)(&buff[10]) = be2me_16(dlen);	//length of the es descriptors
+	
+	*(uint16_t *)(&buff[4]) = be2me_16(len - 6 + 4);	// length field fixed, including size of CRC32
+	
+	*(uint32_t *)(&buff[len]) = CalcCRC32(buff, len);
+	
+	len += 4;	//for crc
+	
+	return len;
+}
+
+static int write_mpeg_pes_header(muxer_headers_t *h, uint8_t *pes_id, uint8_t *buff, uint16_t plen, int stuffing_len, int mux_type)
+{
+	int len;
+	
+	len = 0;
+	memcpy(&buff[len], pes_id, 4);
+	len += 4;
+
+	buff[len] = buff[len+1] = 0;	//fake len
+	len += 2;
+
+	if(mux_type == MUX_MPEG1)
+	{
+		if(stuffing_len > 0)
+		{
+			memset(&buff[len], 0xff, stuffing_len);
+			len += stuffing_len;
+		}
+		
+		if(h->buffer_size > 0)
+		{
+			write_mpeg_std(&buff[len], h->buffer_size, h->type, 0x40); // 01 is pes1 format	
+			len += 2;
+		}
+	}
+	else	//MPEG2
+	{
+		buff[len] = (h->pes_is_aligned ? 0x84 : 0x80);	//0x10... 
+		len++;
+		buff[len] = ((h->buffer_size > 0) ?  1 : 0) | (h->pts ? (h->dts ? 0xC0 : 0x80) : 0);	//pes extension + pts/dts flags
+		len++;
+		buff[len] = (h->pts ? (h->dts ? 10 : 5) : 0) + ((h->buffer_size > 0) ?  3 : 0) + stuffing_len;//pts + std + stuffing
+		len++;
+	}
+	
+	
+	if(h->pts)
+	{
+		write_mpeg_ts(&buff[len], h->pts, (h->dts ? 0x30 : 0x20)); // 001x and both PTS/DTS
+		len += 5;
+		
+		if(h->dts)
+		{
+			write_mpeg_ts(&buff[len], h->dts, 0x10); // 0001 before DTS
+			len += 5;
+		}
+	}
+	else
+	{
+		if(mux_type == MUX_MPEG1)
+		{
+			buff[len] = 0x0f;
+			len += 1;
+		}
+	}
+
+	
+	if(mux_type == MUX_MPEG2)
+	{	
+		if(h->buffer_size > 0)
+		{
+			buff[len] = 0x10;	//std flag
+			len++;
+			
+			write_mpeg_std(&buff[len], h->buffer_size, h->type, 0x40);
+			len += 2;
+		}
+		
+		if(stuffing_len > 0)
+		{
+			memset(&buff[len], 0xff, stuffing_len);
+			len += stuffing_len;
+		}
+	}
+
+	if(h->has_pes_priv_headers > 0)
+	{
+		memcpy(&buff[len], h->pes_priv_headers, h->has_pes_priv_headers);
+		len += h->has_pes_priv_headers;	
+	}
+	
+	*((uint16_t*) &buff[4]) = be2me_16(len + plen - 6);	//fix pes packet size	
+	return len;
+}
+
+
+static void write_pes_padding(uint8_t *buff, uint16_t len)
+{
+	//6 header bytes + len-6 0xff chars
+	buff[0] = buff[1] = 0;
+	buff[2] = 1;
+	buff[3] = 0xbe;
+	*((uint16_t*) &buff[4]) = be2me_16(len - 6);
+	memset(&buff[6], 0xff, len - 6);
+}
+
+static void write_psm_block(muxer_t *muxer, FILE *f)
+{
+	uint16_t offset, stuffing_len;
+	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	uint8_t *buff = priv->buff;
+	
+	offset = write_mpeg_pack_header(muxer, buff);
+	offset += write_mpeg_psm(muxer, &buff[offset]);
+	stuffing_len = priv->packet_size - offset;
+	if(stuffing_len > 0)
+	{
+		//insert a PES padding packet
+		write_pes_padding(&buff[offset], stuffing_len);
+		offset += stuffing_len;
+	}
+	fwrite(buff, offset, 1, f);
+	priv->headers_size += offset;
+}
+
+
+static int write_nav_pack(uint8_t *buff)
+{
+	// concatenation of pes_private2 + 03d4 x 0 and pes_private2 + 03fa x 0
+        int len;
+
+	mp_msg(MSGT_MUXER, MSGL_V, "NAV\n");
+	len = 0;
+	*(uint32_t *)(&buff[len]) = be2me_32(PES_PRIVATE2);
+	len += 4;
+	buff[len++] = 0x3;
+	buff[len++] = 0xd4;
+	memset(&buff[len], 0, 0x03d4);
+        len += 0x03d4;
+
+	*(uint32_t *)(&buff[len]) = be2me_32(PES_PRIVATE2);
+	len += 4;
+	buff[len++] = 0x3;
+	buff[len++] = 0xfa;
+	memset(&buff[len], 0, 0x03fa);
+        len += 0x03fa;
+
+	return len;
+}
+
+static uint32_t calc_pes_hlen(int format, muxer_headers_t *h, muxer_priv_t *priv)
+{
+	uint32_t len;
+	
+	if(format == MUX_MPEG1)
+		len = 6;
+	else
+		len = 9;	//era 12
+	
+	if(h->pts)
+	{
+		len += 5;
+		if(h->dts)
+			len += 5;
+	}
+	else if(format == MUX_MPEG1)
+		len += 1;
+	
+	if(h->buffer_size > 0)
+	{
+		if(format == MUX_MPEG2)
+			len += 3;
+		else
+			len += 2;
+	}
+
+	len += h->has_pes_priv_headers;
+	
+	return len;
+}
+
+static uint32_t calc_pack_hlen(muxer_priv_t *priv, muxer_headers_t *h)
+{
+	uint32_t len;
+
+	if(priv->mux == MUX_MPEG1)
+		len = 12;
+	else
+		len = 14;
+	
+	/*if((priv->is_genmpeg1 || priv->is_genmpeg2) && priv->update_system_header)
+		len += (6 + (3*priv->sys_info.cnt));*/
+
+	if(h->min_pes_hlen > 0)
+		len += h->min_pes_hlen;
+	else
+		len += calc_pes_hlen(priv->mux, h, priv);
+	
+	return len;
 }
 
-static void write_mpeg_std(unsigned char *b, unsigned int size, char mod) {
-  if (size)
-    size--; // for round upward
-  if (size < (128 << 8))
-    size >>= 7; // by 128 bytes
-  else {
-    size >>= 10;
-    size |= 0x2000; // by 1kbyte
-  }
-  size++; // round upward
-  b[0] = ((size >> 8) & 0x3f) | 0x40 | mod;
-  b[1] = size & 0xff;
+
+static int write_mpeg_pack(muxer_t *muxer, muxer_stream_t *s, FILE *f, char *bl, uint32_t len, int isoend)
+{
+	size_t tot, offset, pes_hlen, pack_hlen;
+	muxer_priv_t *priv;
+	uint8_t *buff;
+	int stuffing_len = 0, stflen;
+	muxer_headers_t *spriv;
+
+	priv = (muxer_priv_t *) muxer->priv;
+	buff = priv->buff;
+
+	if(isoend)
+	{
+		buff[0] = buff[1] = 0;
+		buff[2] = 1;
+		buff[3] = 0xb9;
+		fwrite(buff, 4, 1, f);
+		return 1;
+	}
+		
+	if((len == 0) || (bl == NULL))			//PACK headers only
+	{
+		offset = write_mpeg_pack_header(muxer, buff);
+		offset += write_mpeg_system_header(muxer, &buff[offset]);
+		
+		//priv->update_system_header = 0;
+		
+		if(priv->is_dvd)
+			offset += write_nav_pack(&buff[offset]);
+			
+		stuffing_len = priv->packet_size - offset;
+		if(stuffing_len > 0)
+		{
+			//insert a PES padding packet
+			write_pes_padding(&buff[offset], stuffing_len);
+			offset += stuffing_len;
+		}
+			
+		fwrite(buff, offset, 1, f);
+		priv->headers_size += offset;
+		tot = offset;
+		muxer->movi_end += tot;
+		
+		return tot;
+	}
+	else
+	{
+		spriv = (muxer_headers_t *) s->priv;
+		
+		mp_msg(MSGT_MUXER, MSGL_V, "\nwrite_mpeg_pack(MUX=%d, len=%u, rate=%u, id=%X, pts: %llu, dts: %llu, scr: %llu, PACK_size:%u\n", 
+		priv->mux, len, muxer->sysrate, s->ckid, spriv->pts, spriv->dts, priv->scr, priv->packet_size);
+		
+		//stflen is the count of stuffing bytes in the pes header itself, 
+		//stuffing_len is the size of the stuffing pes stream (must be at least 7 bytes long)
+		stflen = stuffing_len = 0;
+		offset = 0;
+		offset = pack_hlen = write_mpeg_pack_header(muxer, &buff[offset]);
+		
+		if(priv->update_system_header && (priv->is_genmpeg1 || priv->is_genmpeg2))
+		{
+			pack_hlen += write_mpeg_system_header(muxer, &buff[offset]);
+			priv->update_system_header = 0;
+		}
+
+		offset = pack_hlen;
+		
+		pes_hlen = calc_pes_hlen(priv->mux, spriv, priv);
+		if(spriv->min_pes_hlen > 0)
+		{
+			if(spriv->min_pes_hlen > pes_hlen)
+				stflen = spriv->min_pes_hlen - pes_hlen;
+		}
+			
+		if((len >= priv->packet_size - pack_hlen - max(pes_hlen, spriv->min_pes_hlen)))
+			stuffing_len = 0;
+		else
+			stuffing_len = priv->packet_size - pack_hlen - max(pes_hlen, spriv->min_pes_hlen) - len;
+		
+		if(stuffing_len > 0)
+		{
+			if(stuffing_len < 7)
+			{
+				if(stflen + stuffing_len > 16)
+				{
+					int x = 7 - stuffing_len;
+					stflen -= x;
+					stuffing_len += x;
+				}
+				else
+				{
+					stflen += stuffing_len;
+					stuffing_len = 0;
+				}
+			}
+		}
+		
+		if(priv->skip_padding)	//variable packet size, just for fun and to reduce file size
+		{
+			stuffing_len = 0;
+			len = min(len, priv->packet_size - pack_hlen - pes_hlen - stflen);
+		}
+		else
+			len = priv->packet_size - pack_hlen - pes_hlen - stflen - stuffing_len;
+		
+		mp_msg(MSGT_MUXER, MSGL_V, "LEN=%d, pack: %d, pes: %d, stf: %d, stf2: %d\n", len, pack_hlen, pes_hlen, stflen, stuffing_len);
+
+		pes_hlen = write_mpeg_pes_header(spriv, (uint8_t *) &s->ckid, &buff[offset], len, stflen, priv->mux);
+
+		offset += pes_hlen;
+		
+		fwrite(buff, offset, 1, f);
+		mp_msg(MSGT_MUXER, MSGL_V, "pack_len = %u, pes_hlen = %u, stuffing_len: %d+%d, SCRIVO: %d bytes di payload\n", 
+			pack_hlen, pes_hlen, stuffing_len, stflen, len);
+		fwrite(bl, len, 1, f);
+		
+		offset += len;
+		
+		if(stuffing_len > 0)
+		{
+			//insert a PES padding packet
+			mp_msg(MSGT_MUXER, MSGL_V, "STUFFING: %d\n", stuffing_len);
+			write_pes_padding(buff, stuffing_len);
+			fwrite(buff, stuffing_len, 1, f);
+		}
+		else
+			stuffing_len = 0;
+	
+		offset += stuffing_len;
+		
+		mp_msg(MSGT_MUXER, MSGL_V, "\nwritten len=%d, spriv: pack(%d), pes(%d), stuffing(%d) tot(%d), offset: %d\n", 
+			len, pack_hlen, pes_hlen, stuffing_len, pack_hlen + pes_hlen + stuffing_len, offset);
+		
+		priv->headers_size += pack_hlen + pes_hlen + stuffing_len + stflen;
+		priv->data_size += len;
+		muxer->movi_end += offset;
+			
+		return len;
+	}
+}
+
+
+static void patch_seq(muxer_priv_t *priv, unsigned char *buf)
+{
+	if(priv->vwidth > 0)
+	{
+		buf[4] = (priv->vwidth >> 4) & 0xff;
+		buf[5] &= 0x0f;
+		buf[5] |= (priv->vwidth & 0x0f) << 4;
+	}
+	
+	if(priv->vheight > 0)
+	{
+		buf[5] &= 0xf0;
+		buf[5] |= (priv->vheight >> 8) & 0x0f;
+		buf[6] = priv->vheight & 0xff;
+	}
+	
+	if(priv->vaspect > 0)
+		buf[7] = (buf[7] & 0x0f) | (priv->vaspect << 4);
+	
+	if(priv->vframerate > 0)
+		buf[7] = (buf[7] & 0xf0) | priv->vframerate;
+		
+	if(priv->vbitrate > 0)
+	{
+		buf[8] = (priv->vbitrate >> 10);
+		buf[9] = (priv->vbitrate >> 2);
+		buf[10] = (buf[10] & 0x3f) | (unsigned char) ((priv->vbitrate & 0x4) << 2);
+	}
+}
+
+static void patch_panscan(muxer_priv_t *priv, unsigned char *buf)
+{	//patches sequence display extension (display_horizontal_size and display_vertical_size)
+	//1: 
+	int offset = 1;
+	
+	if(buf[0] & 0x01)
+		offset += 3;
+	
+	if(priv->panscan_width > 0)
+	{
+		buf[offset] = (priv->panscan_width >> 6);
+		buf[offset+1] = ((priv->panscan_width & 0x3F) << 2) | (buf[offset + 1] & 0x03);
+	}
+	
+	offset++;
+	
+	if(priv->panscan_height > 0)
+	{
+		buf[offset] = (priv->panscan_height >> 13) << 7;
+		buf[offset+1] = (priv->panscan_height >> 5) & 0xFF;
+		buf[offset+2] = ((priv->panscan_height & 0x1F) << 3) | (buf[offset+2] & 0x07);
+	}
+}
+
+
+#define max(a, b) ((a) >= (b) ? (a) : (b))
+#define min(a, b) ((a) <= (b) ? (a) : (b))
+
+
+static uint32_t get_audio_frame_size(muxer_headers_t *spriv, uint8_t *buf, int format, int samples_ps)
+{
+	uint32_t sz, tmp;
+	
+#ifdef USE_LIBA52
+#include "../liba52/a52.h"
+	if(format == 0x2000)
+	{
+		int t1, t2, t3;
+		sz = (uint32_t) a52_syncinfo(buf, &t1, &t2, &t3);
+		if(sz)
+			return sz;
+	}
+#endif
+	tmp = spriv->bitrate * (format == 0x2000 ? 1536 : 1152);
+	sz = tmp / samples_ps;
+	if(sz % 2)
+		sz++;
+		
+	return sz;
+}
+
+
+static int reorder_frame(muxer_headers_t *spriv, uint8_t *ptr, size_t len, uint8_t pt, uint32_t temp_ref, uint64_t idur)
+{
+	uint16_t idx = 0, move=0;
+	
+	/*	HOW TO REORDER FRAMES IN DECODING ORDER:
+		current frame is n
+		IF pt(n)==I or P and
+			n>0 && temp_ref(n) > temp_ref(n-1) && pt(n-1 .. n-m)==B
+				then insert frame n before frame n-m 
+				and shift forward the others
+	*/
+
+	idx = spriv->framebuf_used;
+	if(spriv->reorder)
+	{
+		//stores the frame in decoding order
+		if((idx > 0) && ((pt == I_FRAME) || (pt == P_FRAME)))
+		{
+			if((spriv->framebuf[idx - 1].type == B_FRAME) && (spriv->framebuf[idx - 1].temp_ref == temp_ref-1))
+			{
+				while((spriv->framebuf[idx - 1].type == B_FRAME) && (spriv->framebuf[idx - 1].temp_ref < temp_ref) && (idx > 0))
+					idx--;
+				move = spriv->framebuf_used - idx;	//from idx there are 'move' frames to move forward
+			}
+		}
+	}
+	
+	//now idx is the position where we should store the frame 
+	if(idx+move >= spriv->framebuf_cnt)
+	{	//realloc
+		//fprintf(stderr, "\nREALLOC1: %d\n", (int) spriv->framebuf_cnt+1);
+		spriv->framebuf = (mpeg_frame_t*) realloc(spriv->framebuf, (spriv->framebuf_cnt+1)*sizeof(mpeg_frame_t));
+		if(spriv->framebuf == NULL)
+		{
+			mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(idx), abort\n");
+			return 0;
+		}
+		
+		spriv->framebuf[spriv->framebuf_cnt].size = 0;
+		spriv->framebuf[spriv->framebuf_cnt].alloc_size = 0;
+		
+		spriv->framebuf[spriv->framebuf_cnt].buffer = (uint8_t*) malloc(len);
+		if(spriv->framebuf[spriv->framebuf_cnt].buffer == NULL)
+		{
+			mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n");
+			return 0;
+		}
+		spriv->framebuf[spriv->framebuf_cnt].alloc_size = len;		
+		spriv->framebuf_cnt++;
+	}
+	
+
+	
+	while(move > 0)
+	{
+		mpeg_frame_t f;
+		
+		f = spriv->framebuf[move + idx];
+		spriv->framebuf[move + idx] = spriv->framebuf[move + idx - 1];
+		spriv->framebuf[move + idx - 1] = f;
+		move--;
+	}
+	
+	if(spriv->framebuf[idx].alloc_size < len)
+	{
+		spriv->framebuf[idx].buffer = realloc(spriv->framebuf[idx].buffer, len);
+		if(spriv->framebuf[idx].buffer == NULL)
+		{
+			mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n");
+			return 0;
+		}
+		spriv->framebuf[idx].alloc_size = len;
+	}
+	
+	mp_msg(MSGT_MUXER, MSGL_DBG2, "\nIDX: %u, type: %c, temp_ref: %u, ptr: %p, len: %u, alloc: %u, buffer: %p\n", 
+		(uint32_t) idx, FTYPE(pt), temp_ref, ptr, (uint32_t) len, (uint32_t) spriv->framebuf[idx].alloc_size, spriv->framebuf[idx].buffer);
+		
+	memcpy(spriv->framebuf[idx].buffer, ptr, len);
+	spriv->framebuf[idx].size = len;
+	spriv->framebuf[idx].temp_ref = temp_ref;
+	spriv->framebuf[idx].type = pt;
+	spriv->framebuf[idx].idur = idur;
+	spriv->framebuf_used++;
+	
+	return 1;
+}
+
+
+static uint32_t dump_audio(muxer_t *muxer, muxer_stream_t *as, uint32_t abytes, int force)
+{
+	uint32_t len = 0, sz;
+	uint64_t num_frames = 0, next_pts;
+	uint16_t rest;
+	int64_t tmp;
+	double delta_pts;
+	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	muxer_headers_t *apriv = (muxer_headers_t*) as->priv;
+	
+	if((abytes < apriv->frame_size) && (! force))	//pl_size
+	//if((abytes < apriv->max_pl_size) && (! force))	//pl_size
+	{
+		apriv->is_late = 1;
+		mp_msg(MSGT_MUXER, MSGL_V, "NOT SAVING: %u bytes\n", abytes);
+		return 0;
+	}
+	
+	abytes = min(abytes, as->b_buffer_len);			//available bytes
+	if(! abytes)
+		return 0;
+
+	if(as->ckid == be2me_32(0x1bd))
+		apriv->has_pes_priv_headers = 4;
+	else
+		apriv->has_pes_priv_headers = 0;
+
+	rest = (apriv->size % apriv->frame_size);
+	if(rest)
+		rest = apriv->frame_size - rest;
+	
+	sz = priv->packet_size - calc_pack_hlen(priv, apriv);	//how many payload bytes we are about to write
+	num_frames = (sz + apriv->frame_size - 1 - rest) / apriv->frame_size;
+	
+	mp_msg(MSGT_MUXER, MSGL_V, "\nAUDIO: tot=%llu, sz=%u bytes, FRAMES: %llu * %u, REST: %u, DELTA_PTS: %u\n", 
+		apriv->size, sz, num_frames, (uint32_t) apriv->frame_size, (uint32_t) rest, (uint32_t) ((num_frames * apriv->delta_pts) >> 10));
+	
+	next_pts = ((uint64_t) (num_frames * apriv->delta_pts)) + apriv->pts;
+	if(((priv->scr + (63000*1024)) < next_pts) && (priv->scr < apriv->pts) && (! force))
+	{
+		apriv->is_late = 1;
+		return 0;
+	}
+
+	if(as->ckid == be2me_32(0x1bd))
+	{
+		apriv->pes_priv_headers[0] = 0x80;
+		apriv->pes_priv_headers[1] = num_frames;
+		apriv->pes_priv_headers[2] = ((rest+1) >> 8) & 0xff;	//256 * 0 ...
+		apriv->pes_priv_headers[3] = (rest+1) & 0xff;		// + 1 byte(s) to skip
+	}
+	
+	if((priv->is_xsvcd || priv->is_xvcd) && apriv->size == 0)
+		apriv->buffer_size = 4*1024;
+
+	if(apriv->pts < priv->scr)
+		mp_msg(MSGT_MUXER, MSGL_ERR, "\nERROR: SCR: %llu, APTS: %llu, DELTA=-%.3lf secs\n", 
+			priv->scr, apriv->pts, (double) ((priv->scr - apriv->pts)/92160000.0));
+	
+	len = write_mpeg_pack(muxer, as, muxer->file, &(as->b_buffer[as->b_buffer_ptr]), abytes, 0);
+	if((priv->is_xsvcd || priv->is_xvcd) && apriv->size == 0)
+		apriv->buffer_size = 0;
+	
+	apriv->size += len;
+	apriv->pts = next_pts;
+	
+	mp_msg(MSGT_MUXER, MSGL_DBG2, "NUM_FRAMES: %llu\n", num_frames);
+	
+	tmp = apriv->pts - priv->scr;
+	if((abs(tmp) > (63000*1024)) || (apriv->pts <= priv->scr))
+	{
+		double d;
+		d = (double) apriv->frame_size / (double) apriv->bitrate;
+		d *= (tmp - (63000*1024));
+		apriv->compensate = (uint32_t) d;
+		
+		if(abs(tmp) > 92160000)	//usually up to 1 second it still acceptable
+			mp_msg(MSGT_MUXER, MSGL_ERR, "\nWARNING: SCR: %llu, APTS: %llu, DELTA=%.3lf secs, BYTES=%d\n", priv->scr, apriv->pts, 
+				(((double) tmp)/92160000.0), apriv->compensate);
+	}
+
+	mp_msg(MSGT_MUXER, MSGL_V, "\nWRITTEN AUDIO: %u bytes, TIMER: %.3lf, FRAMES: %llu * %u, DELTA_PTS: %.3lf\n", 
+		len, (double) (apriv->pts/92160000), num_frames, (uint32_t) apriv->frame_size, delta_pts);
+	
+	as->b_buffer_ptr += len;
+	as->b_buffer_len -= len;
+	
+	if(as->b_buffer_len > 0)
+		memmove(as->b_buffer, &(as->b_buffer[as->b_buffer_ptr]), as->b_buffer_len);
+	as->b_buffer_ptr = 0;
+	
+	return len;
+}
+
+static void drop_delayed_audio(muxer_t *muxer, muxer_stream_t *as, int64_t size)
+{
+	//muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	muxer_headers_t *apriv = (muxer_headers_t *) as->priv;
+	int64_t size1, div, rest;	//initial value
+	double rest_pts;
+	
+	div = size / apriv->frame_size;
+	rest = size % apriv->frame_size;
+	if(rest >= apriv->frame_size / 2)
+		size1 = (div+1) * apriv->frame_size;
+	else
+		size1 = (div) * apriv->frame_size;
+
+	fprintf(stderr, "SIZE1: %llu, LEN: %llu\n", size1, (uint64_t)as->b_buffer_len);
+	size1 = min(size1, as->b_buffer_len);
+	memmove(as->b_buffer, &(as->b_buffer[size]), as->b_buffer_len - size1);
+	as->b_buffer_len -= size1;
+	
+	rest = size1 - size;
+	rest_pts = (double) rest / (double) apriv->bitrate;
+	apriv->pts += (int64_t) (92160000.0 * rest_pts);
+	mp_msg(MSGT_MUXER, MSGL_V, "DROPPED: %lld bytes, REST= %lld, REST_PTS: %.3lf, AUDIO_PTS%.3lf\n", size1, rest, rest_pts, (double) (apriv->pts/92160000.0));
 }
 
-static int write_mpeg_block(muxer_t *muxer, muxer_stream_t *s, FILE *f, char *bl, size_t len, int isoend){
-  size_t sz; // rest in block buffer
-  unsigned char buff[12]; // 0x1ba header
-  unsigned int mints=0;
-  uint16_t l1;
+
+static void save_delayed_audio(muxer_t *muxer, muxer_stream_t *as, uint64_t dur)
+{
+	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	muxer_headers_t *apriv = (muxer_headers_t *) as->priv;
+	uint64_t init_pts, last_pts;	//initial value
+	
+	init_pts = apriv->pts;
+	mp_msg(MSGT_MUXER, MSGL_V, "DUR: %llu, DIFF: %llu\n", dur, apriv->pts - init_pts);
+	while(dur > apriv->pts - init_pts)
+	{
+		priv->scr = (92160000 * apriv->size) / apriv->bitrate;
+		last_pts = apriv->pts;
+		dump_audio(muxer, as, as->b_buffer_len, 0);
+		mp_msg(MSGT_MUXER, MSGL_V, "DUR: %llu, DIFF: %llu, SCR: %llu\n", dur, apriv->pts - init_pts, priv->scr);
+	}
+	
+	//priv->init_delay_pts = last_pts;
+	priv->init_delay_pts = (90 * 1024 * abs(conf_init_adelay)) + apriv->init_pts - (90 * 1024 * abs(conf_init_vpts));
+	if(priv->init_delay_pts <= priv->scr)
+		priv->init_delay_pts = last_pts;
+	mp_msg(MSGT_MUXER, MSGL_INFO, "INIT_VPTS: %llu (%.3lf)\n", priv->init_delay_pts, (double) (priv->init_delay_pts/92160000.0));
+}
+
+
+static inline void update_scr(muxer_priv_t *priv, uint32_t len, uint32_t totlen, double mult)
+{
+	uint64_t delta_scr;
+	double perc;
+	
+	perc = (double) len / (double) totlen;
+	
+	delta_scr = (uint64_t) (mult * perc);
+	priv->scr += delta_scr;
+	
+	mp_msg(MSGT_MUXER, MSGL_V, "UPDATE SCR TO %llu (%.3lf): mult is %.3lf,  perc: %.3lf, %u/%u, delta: %llu\n", 
+		priv->scr, (double) (priv->scr/92160000.0), mult, perc, len, totlen, delta_scr);
+}
+
+
+static int calc_frames_to_flush(muxer_headers_t *vpriv)
+{
+	int n, found = 0;
+	
+	if(vpriv->framebuf_used > 0)
+	{
+		n = 0;
+		//let's count how many frames we'll store in the next pack sequence
+		mp_msg(MSGT_MUXER, MSGL_V, "\n");
+		while(n < vpriv->framebuf_used)
+		{
+			mp_msg(MSGT_MUXER, MSGL_V, "n=%d, type=%c, temp_ref=%u\n", n, FTYPE(vpriv->framebuf[n].type), vpriv->framebuf[n].temp_ref);
+			if(n+1 < vpriv->framebuf_used)
+				mp_msg(MSGT_MUXER, MSGL_V, "n+1=%d, type=%c, temp_ref=%u\n", n+1, FTYPE(vpriv->framebuf[n+1].type), vpriv->framebuf[n+1].temp_ref);
+				
+			if(vpriv->framebuf[n].type == I_FRAME)
+			{
+				if(n > 0)
+				{
+					found = 1;
+					break;
+				}
+			}
+
+			n++;
+		}
+	}
+	
+	if(found && (n < vpriv->framebuf_used+1))
+		return n;
+	else
+		return 0;
+}
+
+
+static uint64_t fix_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int n)
+{
+	int i, j, fixed = 0;
+	uint64_t last_dts, last_idur, ret;
+	uint32_t mintr, maxtr;
 
-  mp_dbg(MSGT_MUXER, MSGL_DBG3, " MPEG block: size=%u, scr=%u, rate=%u, id=%X;", len, muxer->file_end, muxer->sysrate, s->ckid);
-  if (s->b_buffer_ptr == 0) { // 00001111 if no PTS
-    s->b_buffer[0] = 0xf;
-    s->b_buffer_ptr = 1;
-    sz = MUXER_MPEG_DATASIZE-1;
-  } else if (s->b_buffer_ptr > MUXER_MPEG_DATASIZE) {
-    printf ("Unknown error in write_mpeg_block()!\n");
-    return 0;
-  } else {
-    sz = MUXER_MPEG_DATASIZE - s->b_buffer_ptr;
-    if (s->b_buffer[7] == 0xff) // PTS not set yet
-      s->b_buffer[11] = 0xf; // terminate stuFFing bytes
-  }
-  if (len > sz)
-    len = sz;
-  *(uint32_t *)buff = be2me_32 (0x1ba);
-  write_mpeg_ts (buff+4, muxer->file_end, 0x20); // 0010 and SCR
-  write_mpeg_rate (buff+9, muxer->sysrate);
-  fwrite (buff, 12, 1, f);
-  fwrite (&s->ckid, 4, 1, f); // stream_id
-  memset (buff, 0xff, 12); // stuFFing bytes
-  sz -= len;
-  // calculate padding bytes in buffer
-  while (mints < s->b_buffer_ptr && s->b_buffer[mints] == 0xff) mints++;
-  if (mints+sz < 12) { // cannot write padding block so write up to 12 stuFFing bytes
-    l1 = be2me_16 (MUXER_MPEG_DATASIZE);
-    fwrite (&l1, 2, 1, f);
-    mints = 0; // so stuFFed bytes will be written all
-    if (sz)
-      fwrite (buff, sz, 1, f);
-    sz = 0; // no padding block anyway
-  } else { // use padding block
-    if (sz > 6) // sufficient for PAD header so don't shorter data
-      mints = 0;
-    else
-      sz += mints; // skip stuFFing bytes (sz>8 here)
-    l1 = be2me_16 (s->b_buffer_ptr+len-mints);
-    fwrite (&l1, 2, 1, f);
-  }
-  if (s->b_buffer_ptr)
-    fwrite (s->b_buffer+mints, s->b_buffer_ptr-mints, 1, f);
-  if (len)
-    fwrite (bl, len, 1, f);
-  if (sz > 6) { // padding block (0x1be)
-    uint32_t l0;
+	ret = 0;
+	if((vpriv->size == 0) && (fixed == 0))	//first pts adjustment, only at the beginning of the stream to manage BBI structures
+	{
+		int delay = 0;
+		for(i = 0; i < n; i++)
+		{
+			if(vpriv->framebuf[i].type == I_FRAME)
+			{
+				for(j = i + 1; j < n; j++)
+				{
+					if(vpriv->framebuf[i].temp_ref >= vpriv->framebuf[j].temp_ref)
+					{
+						ret += vpriv->framebuf[j].idur;
+						delay++;
+						fixed = 1;
+					}
+				}
+				if(fixed)
+					break;
+			}
+		}
+		
+		if(! fixed)
+			ret = 0;
+		else
+			vpriv->last_pts += ret;
+		
+		mp_msg(MSGT_MUXER, MSGL_INFO, "INITIAL DELAY of %d frames\n", delay);
+	}
+	
+	//KLUDGE BEGINS: Gop header (0x000001b8 in the video stream that signals a temp_ref wraparound) is _not_ mandatory, 
+	//so if we don't detect the right wraparound we will have a totally wrong timestamps assignment; let's go on
+	mintr = vpriv->framebuf[0].temp_ref;
+	maxtr = vpriv->framebuf[0].temp_ref;
+	for(i = 0; i < n; i++)
+	{
+		mintr = min(vpriv->framebuf[i].temp_ref, mintr);
+		maxtr = max(vpriv->framebuf[i].temp_ref, maxtr);
+	}
+	if(maxtr - mintr > 600)	//there must be a temp_ref wraparound
+	{
+		mp_msg(MSGT_MUXER, MSGL_INFO, "\nDETECTED possible temp_ref wraparound in the videostreams: n=%d, mintr=%u, maxtr=%u\n", n, mintr, maxtr);
+		for(i = 0; i < n; i++)
+		{
+			if(vpriv->framebuf[i].temp_ref < 1000)
+				vpriv->framebuf[i].temp_ref += 1024;
+		}	
+	}
+	//KLUDGE ENDS
+	
+	
+	for(i = 0; i < n; i++)
+	{
+		vpriv->framebuf[i].pts = vpriv->last_pts;
+		
+		for(j = 0; j < n; j++)
+		{
+			if((vpriv->framebuf[i].temp_ref >= vpriv->framebuf[j].temp_ref) && (i != j))
+			{
+				vpriv->framebuf[i].pts += vpriv->framebuf[j].idur;
+			}
+		}
+	}
 
-    if (isoend)
-      l0 = be2me_32 (0x1b9);
-    else
-      l0 = be2me_32 (0x1be);
-    sz -= 6;
-    l1 = be2me_16 (sz);
-    fwrite (&l0, 4, 1, f);
-    fwrite (&l1, 2, 1, f);
-    memset (s->b_buffer, 0xff, sz); // stuFFing bytes
-    fwrite (s->b_buffer, sz, 1, f);
-  }
-  s->b_buffer_ptr = 0;
-  muxer->movi_end += MUXER_MPEG_BLOCKSIZE;
-  // prepare timestamps for next pack
-  mints = (MUXER_MPEG_BLOCKSIZE*90000/muxer->sysrate)+1; // min ts delta
-  sz = (int)(s->timer*90000) + MPEG_STARTPTS; // new PTS
-  if (sz > muxer->file_end)
-    sz -= muxer->file_end; // suggested ts delta
-  else
-  {
-    sz = 0;
-    printf ("Error in stream: PTS earlier than SCR!\n");
-  }
-  if (sz > MPEG_MAX_PTS_DELAY) {
-//    printf ("Warning: attempt to set PTS to SCR delay to %u \n", sz);
-    mints = sz-MPEG_MAX_PTS_DELAY; // try to compensate
-    if (mints > MPEG_MAX_SCR_INTERVAL) {
-      printf ("Error in stream: SCR interval %u is too big!\n", mints);
-    }
-  } else if (sz > 54000) // assume 0.3...0.7s is optimal
-    mints += (sz-45000)>>2; // reach 0.5s in 4 blocks ?
-  else if (sz < 27000) {
-    unsigned int newsysrate = 0;
+	if(vpriv->size == 0)
+		last_dts = vpriv->init_dts = vpriv->framebuf[0].pts - (ret + vpriv->framebuf[0].idur);
+	else
+		last_dts = vpriv->last_dts;
+	
+	last_idur = 0;
+	
+	mp_msg(MSGT_MUXER, MSGL_V, "\n");
+	for(i = 0; i < n; i++)
+	{
+		vpriv->framebuf[i].dts = last_dts + last_idur;
+		last_idur = vpriv->framebuf[i].idur;
+		last_dts = vpriv->framebuf[i].dts;
+		mp_msg(MSGT_MUXER, MSGL_V, "I=%d, type: %c, TR: %u, pts=%.3lf, dts=%.3lf, size=%u\n", 
+			i, FTYPE(vpriv->framebuf[i].type), vpriv->framebuf[i].temp_ref, (double) (vpriv->framebuf[i].pts/92160000.0), 
+			(double) (vpriv->framebuf[i].dts/92160000.0), vpriv->framebuf[i].size);
+	}
+	
+	if((vpriv->size == 0) && (priv->init_delay_pts > 0))
+	{
+		uint64_t diff;
+		
+		for(i = 0; i < vpriv->framebuf_used; i++)
+		{
+			vpriv->framebuf[i].pts += priv->init_delay_pts;
+			vpriv->framebuf[i].dts += priv->init_delay_pts;
+		}
+		
+		diff = vpriv->framebuf[0].pts - vpriv->framebuf[0].dts;
+		if(vpriv->init_pts >= diff)
+			vpriv->init_dts = vpriv->init_pts - diff;
+		else
+			vpriv->init_dts = diff;
+		
+		vpriv->last_dts +=  priv->init_delay_pts;
+		
+		vpriv->init_pts = 0;
+		vpriv->last_pts +=  priv->init_delay_pts;
+		
+		priv->init_delay_pts = 0;
+		mp_msg(MSGT_MUXER, MSGL_INFO, "INIT delayed video timestamps: PTS=%.3lf, DTS=%.3lf, DUR=%.3lf\n", 
+			(double) (vpriv->last_pts/92160000.0), (double) (vpriv->last_dts/92160000.0), (double) (vpriv->framebuf[0].idur/92160000.0));
+	}
+	
+	return ret;
+}
+
 
-    if (s->timer > 0.5) // too early to calculate???
-      newsysrate = muxer->movi_end/(s->timer*0.4); // pike-factor 2.5 (8dB)
-    if (sz < MPEG_MIN_PTS_DELAY)
-      printf ("Error in stream: PTS to SCR delay %u is too little!\n", sz);
-    if (muxer->sysrate < newsysrate)
-      muxer->sysrate = newsysrate; // increase next rate to current rate
-    else if (!newsysrate)
-      muxer->sysrate += muxer->sysrate>>3; // increase next rate by 25%
-  }
-  muxer->file_end += mints; // update the system timestamp
-  return len;
+static void check_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int i)
+{
+	uint64_t dpts;
+	
+	dpts = max(vpriv->last_saved_pts, vpriv->pts) - min(vpriv->last_saved_pts, vpriv->pts);
+	dpts += vpriv->framebuf[i].idur;
+
+	if((!priv->ts_allframes) && (
+		(priv->is_dvd && (vpriv->framebuf[i].type != I_FRAME)) ||
+		((priv->is_genmpeg1 || priv->is_genmpeg2) && (vpriv->framebuf[i].type != I_FRAME) && (dpts < 64512000)))	//0.7 seconds
+	)
+		vpriv->pts = vpriv->dts = 0;
+	
+	if(vpriv->dts && ((vpriv->dts < priv->scr) || (vpriv->pts <= vpriv->dts)))
+	{
+		mp_msg(MSGT_MUXER, MSGL_V, "\nWARNING, SCR: %.3lf, DTS: %.3lf, PTS: %.3lf\n", 
+		(double) priv->scr/92160000.0,(double) vpriv->dts/92160000.0, (double) vpriv->pts/92160000.0);
+		vpriv->dts = 0;
+	}
+	
+	if(vpriv->pts && (vpriv->pts <= priv->scr))
+	{
+		mp_msg(MSGT_MUXER, MSGL_ERR, "ERROR: SCR: %.3lf, VPTS: %.3lf, DELTA=-%.3lf secs\n", 
+		(double) (priv->scr/92160000.0), (double)(vpriv->pts/92160000.0), (double) ((priv->scr - vpriv->pts)/92160000.0));
+		vpriv->pts = vpriv->dts = 0;
+	}
+	
+	if(vpriv->pts)
+		vpriv->last_saved_pts = vpriv->pts;
+}
+
+static uint32_t calc_audio_chunk_size(muxer_stream_t *as, double duration, int finalize)
+{
+	muxer_headers_t *apriv;
+	uint32_t x, div, rest, abytes;
+	double adur;
+	uint64_t iaduration;
+	
+	apriv = (muxer_headers_t*) as->priv;
+	abytes = (uint32_t) (duration * apriv->bitrate); //size of audio data to write
+	x = (abytes + apriv->max_pl_size - 1) / apriv->max_pl_size;
+	x *= apriv->max_pl_size;
+	adur = (double) x / (double) apriv->bitrate;
+	iaduration = (uint64_t) ((double) 92160000 * adur);
+
+	abytes -= apriv->compensate;
+	div = abytes / apriv->max_pl_size;
+	rest = abytes % apriv->max_pl_size;
+	if(apriv->compensate > 0)
+		abytes = apriv->max_pl_size * (div - 1);
+	else if(apriv->compensate < 0)
+		abytes = apriv->max_pl_size * (div + 1);
+	else
+		abytes = apriv->max_pl_size * (rest ? div + 1 : div);
+	apriv->compensate = 0;
+
+	if(finalize)
+		abytes = as->b_buffer_len;
+
+	return abytes;
 }
 
-static void set_mpeg_pts(muxer_t *muxer, muxer_stream_t *s, unsigned int pts) {
-  unsigned int dts, nts;
+static int flush_buffers(muxer_t *muxer, int finalize)
+{
+	int i, n, pl_size, found;
+	size_t saved;
+	uint32_t abytes, vbytes, bytes = 0, frame_bytes = 0, audio_rest = 0, tot = 0, muxrate;
+	uint32_t offset;
+	uint64_t idur, init_delay = 0;
+	muxer_stream_t *s, *vs, *as;
+	muxer_headers_t *vpriv = NULL, *apriv = NULL;
+	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	uint8_t *tmp;
+	double mult, duration;
+	uint64_t iduration;
+	mpeg_frame_t temp_frame;
+	
+	/* 
+		analyzes all streams and decides what to flush
+		trying to respect an interleaving distribution
+		equal to the v_bitrate/a_bitrate proportion
+	*/
+init:
+	n = 0;
+	vs = as = NULL;
+	abytes = vbytes = found = 0;
+	for(i = 0; i < muxer->avih.dwStreams; i++)
+	{
+		s = muxer->streams[i];
+		if(s->type == MUXER_TYPE_VIDEO)
+		{
+			vs = muxer->streams[i];
+			vpriv = (muxer_headers_t*) vs->priv;
+			n = found = calc_frames_to_flush(vpriv);
+		}
+		else if(s->type == MUXER_TYPE_AUDIO)
+			as = s;
+	}
+	
+	if((! found) && finalize)
+	{
+		if(vpriv != NULL)
+			found = n = vpriv->framebuf_used;
+	}
+
+	if(found)
+	{
+		mp_msg(MSGT_MUXER, MSGL_V, "\nVIDEO, FLUSH %d frames (of %d), 0 to %d\n", n, vpriv->framebuf_used, n-1);
+
+		tmp = priv->tmp;
+		vbytes = 0;
+		vpriv = (muxer_headers_t*) vs->priv;
+		
+		if(priv->residual_cnt)
+		{
+			mpeg_frame_t *f = &(vpriv->framebuf[0]);
+			size_t sz = f->size + priv->residual_cnt;
+			
+			if(f->alloc_size < sz)
+			{
+				f->buffer = (uint8_t *) realloc(f->buffer, sz);
+				f->alloc_size = sz;
+			}
+			memmove(&(f->buffer[priv->residual_cnt]), f->buffer, f->size);
+			memcpy(f->buffer, priv->residual, priv->residual_cnt);
+			f->size += priv->residual_cnt;
+			priv->residual_cnt = 0;
+		}
+		
+		duration = 0;
+		iduration = 0;
+		for(i = 0; i < n; i++)
+		{
+			vbytes += vpriv->framebuf[i].size;
+			iduration += vpriv->framebuf[i].idur;
+		}
+		duration = (double) (iduration / 92160000.0);
+		
+		if(vpriv->is_mpeg12)
+			init_delay = fix_pts(priv, vpriv, n);
+		else
+			init_delay = 0;
+			
+		if(as != NULL)
+		{
+			apriv = (muxer_headers_t*) as->priv;
+			abytes = calc_audio_chunk_size(as, duration, finalize);
+			
+			if((abytes / apriv->max_pl_size) > n)
+				audio_rest = (abytes - (apriv->max_pl_size * n)) / n;
+			else
+				audio_rest = 0;
+			
+			if(as->b_buffer_len < abytes)
+			{
+				mp_msg(MSGT_MUXER, MSGL_V, "Not enough audio data (%u < %u), exit\n", as->b_buffer_len, abytes);
+				return 0;
+			}
+		}
+		
+		if((as != NULL) && (init_delay > 0))
+		{
+			if(apriv->size == 0)
+				apriv->pts += init_delay;
+		}
+		
+		saved = 0;
+		bytes = vbytes + abytes;
+		muxrate = (uint32_t) ((double) bytes/duration);
+		if(muxrate > muxer->sysrate && (priv->is_genmpeg1 || priv->is_genmpeg2))
+		{
+			mp_msg(MSGT_MUXER, MSGL_V, "NEW MUXRATE: %u -> %u\n", muxrate, muxer->sysrate);
+			muxer->sysrate = muxrate;
+		}
+		
+		idur = 0;
+		offset = 0;
+		priv->scr = vpriv->framebuf[0].dts - vpriv->init_dts;
+		
+		if((priv->is_xvcd || priv->is_xsvcd) && (vpriv->size == 0))
+			vpriv->buffer_size = (priv->is_xvcd ? 46 : 230)*1024;
+			
+		i = 0;
+		while(i < n)
+		{
+			int frame_begin = 1, update;
+			uint32_t pl_size = 0, target_size;
+			uint8_t *buf;
+			
+			mp_msg(MSGT_MUXER, MSGL_V, "FRAME: %d, type: %c, TEMP_REF: %u, SIZE: %u\n",
+				i, FTYPE(vpriv->framebuf[i].type), vpriv->framebuf[i].temp_ref, vpriv->framebuf[i].size);
+			
+			vpriv->pts = vpriv->framebuf[i].pts;
+			vpriv->dts = vpriv->framebuf[i].dts;
+			check_pts(priv, vpriv, i);
+			
+			if(priv->is_dvd && (vpriv->framebuf[i].type == I_FRAME) && (offset == 0))
+			{
+				write_mpeg_pack(muxer, NULL, muxer->file, NULL, 0, 0);	//insert fake Nav Packet
+				vpriv->pes_is_aligned = 1;
+			}
+			
+			offset = 0;
+			vbytes = vpriv->framebuf[i].size;
+			while(vbytes > 0 && (i < n))
+			{
+				target_size = priv->packet_size - calc_pack_hlen(priv, vpriv);
+				if((vbytes >= target_size) || ((vbytes < target_size) && (i == n-1)))
+				{
+					buf = &(vpriv->framebuf[i].buffer[offset]);
+					pl_size = vbytes;
+					update = 1;
+				}
+				else
+				{
+					uint32_t tmp_offset = 0;
+					
+					if(offset == 0)
+					{
+						vpriv->pts = vpriv->framebuf[i].pts;
+						vpriv->dts = vpriv->framebuf[i].dts;
+						check_pts(priv, vpriv, i);
+					}
+					else if(i < n-1)
+					{
+						vpriv->pts = vpriv->framebuf[i+1].pts;
+						vpriv->dts = vpriv->framebuf[i+1].dts;
+						check_pts(priv, vpriv, i+1);
+					}
+					else
+						vpriv->pts = vpriv->dts = 0;
+					
+					target_size = priv->packet_size - calc_pack_hlen(priv, vpriv);	//it was only priv->packet_size
+					update = 0;
+					
+					while((tmp_offset < target_size) && (i < n))
+					{
+						pl_size = min(target_size - tmp_offset, vbytes);
+						memcpy(&(tmp[tmp_offset]), &(vpriv->framebuf[i].buffer[offset]), pl_size);
+						tmp_offset += pl_size;
+						offset += pl_size;
+						vbytes -= pl_size;
+					
+						if(vbytes == 0)	//current frame is saved, pass to the next
+						{
+							i++;
+							vbytes = vpriv->framebuf[i].size;
+							offset = 0;
+							frame_begin = 1;
+						}
+					}
+					buf = tmp;
+					pl_size = tmp_offset;
+				}
+			
+				
+				if((pl_size < priv->packet_size - calc_pack_hlen(priv, vpriv)) && !finalize && (i >= n - 1))
+				{
+					memcpy(priv->residual, buf, pl_size);
+					priv->residual_cnt = pl_size;
+					pl_size = update = vbytes = 0;	
+				}
+				if(pl_size)
+					pl_size = write_mpeg_pack(muxer, vs, muxer->file, buf, pl_size, 0);
+				vpriv->pes_is_aligned = 0;
+				vpriv->pts = vpriv->dts = 0;
+				vpriv->buffer_size = 0;
+				vpriv->size += pl_size;
+				if(update)
+				{
+					vbytes -= pl_size;
+					offset += pl_size;
+				}
+				
+				/* this is needed to calculate SCR */
+				frame_bytes = max(vpriv->framebuf[i].size, priv->packet_size) + priv->packet_size;
+				if(abytes > 0)
+					//frame_bytes += min(apriv->max_pl_size, priv->packet_size) + audio_rest;
+					frame_bytes += min(apriv->max_pl_size, abytes) + audio_rest;
+				
+				if(priv->ts_allframes)
+				{
+					tot = frame_bytes;
+					mult = (double) vpriv->framebuf[min(i, n-1)].idur;
+				}
+				else
+				{
+					tot = bytes;
+					//mult = (double) (max(iduration, iaduration));
+					mult = (double) (iduration);
+				}
+				update_scr(priv, pl_size, tot, mult);
+
+				
+				if(abytes > 0 && frame_begin)	//it's time to save audio
+				{
+					pl_size = dump_audio(muxer, as, abytes, finalize);
+					if(pl_size > 0)
+					{
+						abytes -= pl_size;
+						update_scr(priv, pl_size, tot, mult);
+					}
+				}
+				
+				frame_begin = 0;
+			}
+			
+			i++;
+		}
+
+		
+		if(vpriv->is_mpeg12)
+		{
+			for(i = 0; i < n; i++)
+			{
+				vpriv->last_dts = vpriv->framebuf[i].dts;
+				if(vpriv->framebuf[i].pts >= vpriv->last_pts)
+				{
+					vpriv->last_pts = vpriv->framebuf[i].pts;
+					idur = vpriv->framebuf[i].idur;
+				}
+			}
+			
+			vpriv->last_dts += vpriv->framebuf[n-1].idur;
+			vpriv->last_pts += idur;
+		}
+
+		for(i = n; i < vpriv->framebuf_used; i++)
+		{
+			temp_frame = vpriv->framebuf[i - n];
+			vpriv->framebuf[i - n] = vpriv->framebuf[i];
+			vpriv->framebuf[i] = temp_frame;
+		}
+		vpriv->framebuf_used -= n;
+
 
-  if (s->b_buffer_ptr != 0 && s->b_buffer[7] != 0xff)
-    return; // already set
-  if (s->b_buffer_ptr == 0) {
-    memset (s->b_buffer, 0xff, 7); // reserved for PTS or STD, stuFFing for now
-    s->b_buffer_ptr = 12;
-  }
-  dts = (int)(s->timer*90000) + MPEG_STARTPTS; // PTS
-  if (pts) {
-    write_mpeg_ts (s->b_buffer+2, pts, 0x30); // 0011 and both PTS/DTS
-  } else {
-    write_mpeg_ts (s->b_buffer+7, dts, 0x20); // 0010 and PTS only
-    return;
-  }
-  nts = dts - muxer->file_end;
-//  if (nts < mpeg_min_delay) mpeg_min_delay = nts;
-//  if (nts > mpeg_max_delay) mpeg_max_delay = nts;
-  nts = 180000*s->h.dwScale/s->h.dwRate; // two frames
-  if (dts-nts < muxer->file_end) {
-    dts += muxer->file_end;
-    dts /= 2; // calculate average time
-    printf ("Warning: DTS to SCR delay is too small\n");
-  }
-  else
-    dts -= nts/2; // one frame :)
-  mp_dbg(MSGT_MUXER, MSGL_DBG3, ", dts=%u", dts);
-  write_mpeg_ts (s->b_buffer+7, dts, 0x10);
+		if((as != NULL) && priv->has_audio)
+		{
+			while(abytes > 0)
+			{
+				mult = iduration;
+				pl_size = dump_audio(muxer, as, abytes, finalize);
+				if(pl_size > 0)
+				{
+					update_scr(priv, pl_size, bytes, mult);
+					abytes -= pl_size;
+				}
+				else
+					break;
+			}
+		}
+		
+		//goto init;
+	}
+	
+	muxer->file_end = priv->scr;
+	return found;
+}
+
+
+static uint64_t parse_fps(int fps)
+{
+	// 90000 * 1024 / fps
+	switch(fps)
+	{
+		case 239760:
+			return 3843844;
+		case 240000:
+			return 3840000;
+		case 250000:
+			return 3686400;
+		case 299700:
+			return 3075075;
+		case 300000:
+			return 3072000;
+		case 500000:
+			return 1843200;
+		case 599400:
+			return 1537538;
+		case 600000:
+			return 1536000;
+		default:
+			mp_msg(MSGT_MUXER, MSGL_ERR, "ERROR! unknown fps code: %d", fps);
+			return 0;
+	}
+}
+
+static size_t parse_mpeg12_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_headers_t *spriv, float fps, size_t len)
+{
+	size_t ptr = 0, sz = 0, tmp = 0;
+	
+	mp_msg(MSGT_MUXER, MSGL_V,"parse_mpeg12_video, len=%u\n", (uint32_t) len);
+	if(s->buffer[0] != 0 || s->buffer[1] != 0 || s->buffer[2] != 1 || len<6) 
+	{
+		mp_msg(MSGT_MUXER, MSGL_ERR,"Unknown video format, possibly non-MPEG1/2 stream, len=%d!\n", len);
+		return 0;
+	}
+	
+	if(s->buffer[3] == 0 || s->buffer[3] == 0xb3 || s->buffer[3] == 0xb8) 
+	{	// Video (0) Sequence header (b3) or GOP (b8)
+		uint32_t temp_ref;
+		int pt;
+		
+		if(s->buffer[3] == 0xb3) //sequence
+		{
+			//uint8_t fps = s->buffer[7] & 0x0f;
+			mp_header_process_sequence_header(&(spriv->picture), &(s->buffer[4]));
+			spriv->delta_pts = spriv->nom_delta_pts = parse_fps(spriv->picture.fps);
+			
+			spriv->delta_clock = (double) 1/fps;
+			mp_msg(MSGT_MUXER, MSGL_V, "\nFPS: %.3f, FRAMETIME: %.3lf\n", fps, (double)1/fps);
+			if(priv->patch_seq)
+				patch_seq(priv, s->buffer);
+			
+			tmp = 12;
+			if(s->buffer[tmp-1] & 2)
+				tmp += 64;
+			
+			if(s->buffer[tmp-1] & 1)
+				tmp += 64;
+			
+			if(s->buffer[tmp] == 0 && s->buffer[tmp+1] == 0 && s->buffer[tmp+2] == 1 && s->buffer[tmp+3] == 0xb5) 
+				mp_header_process_extension(&(spriv->picture), &(s->buffer[tmp+4]));
+		}
+		
+		
+		if(spriv->picture.mpeg1 == 0 && priv->patch_sde)
+		{
+			while((s->buffer[tmp] != 0 || s->buffer[tmp+1] != 0 || s->buffer[tmp+2] != 1 || s->buffer[tmp+3] != 0xb5 ||
+				((s->buffer[tmp+4] & 0xf0) != 0x20)) &&
+				(tmp < len-5))
+				tmp++;
+			
+			if(tmp < len-5)		//found
+				patch_panscan(priv, &(s->buffer[tmp+4]));
+		}
+		
+		
+
+		if(s->buffer[3])
+		{	// Sequence or GOP -- scan for Picture
+			s->gop_start = s->h.dwLength;
+			while (ptr < len-5 && 
+				(s->buffer[ptr] != 0 || s->buffer[ptr+1] != 0 || s->buffer[ptr+2] != 1 || s->buffer[ptr+3] != 0)) 
+				ptr++;
+		}
+
+		if (ptr >= len-5) 
+		{
+			pt = 0; // Picture not found?!
+			temp_ref = 0;
+			mp_msg(MSGT_MUXER, MSGL_ERR,"Warning: picture not found in GOP!\n");
+		} 
+		else 
+		{
+			pt = (s->buffer[ptr+5] & 0x1c) >> 3;
+			temp_ref = (s->buffer[ptr+4]<<2)+(s->buffer[ptr+5]>>6);
+			mp_msg(MSGT_MUXER, MSGL_V, "Video frame type: %c, TR: %d\n", FTYPE(pt), temp_ref);
+			if(spriv->picture.mpeg1 == 0) 
+			{
+				size_t tmp = ptr;
+			
+				while (ptr < len-5 && 
+					(s->buffer[ptr] != 0 || s->buffer[ptr+1] != 0 || s->buffer[ptr+2] != 1 || s->buffer[ptr+3] != 0xb5)) 
+						ptr++;
+				if(ptr < len-5) 
+				{
+					mp_header_process_extension(&(spriv->picture), &(s->buffer[ptr+4]));
+					if(spriv->picture.display_time >= 50 && spriv->picture.display_time <= 300) 
+						spriv->delta_pts = (spriv->nom_delta_pts * spriv->picture.display_time) / 100;
+				}
+				else 
+					spriv->delta_pts = spriv->nom_delta_pts;
+			
+				ptr = tmp;
+			}
+		}
+		
+		switch (pt) {
+			case 2: // predictive
+			  if (s->ipb[0]) {
+			    sz = len + s->ipb[0];
+			    s->ipb[0] = max(s->ipb[0], s->ipb[2]);
+			    s->ipb[2] = 0;
+			  } else if (s->ipb[2]) {
+			    sz = len + s->ipb[2];
+			    s->ipb[0] = s->ipb[2];
+			    s->ipb[2] = 0;
+			  } else
+			    sz = 4 * len; // no bidirectional frames yet?
+		
+			  s->ipb[1] = len;
+			  break;
+			case 3: // bidirectional
+			  s->ipb[2] += len;
+			  sz = s->ipb[1] + s->ipb[2];
+			  break;
+			default: // intra-coded
+			  sz = len; // no extra buffer for it...
+		}
+
+		reorder_frame(spriv, s->buffer, len, pt, temp_ref, spriv->delta_pts);
+	}
+	
+	mp_msg(MSGT_MUXER, MSGL_V,"parse_mpeg12_video, return %u\n", (uint32_t) len);
+	return sz;
+}
+
+
+static uint64_t fix_mp4_frame_duration(muxer_headers_t *vpriv)
+{
+	uint64_t mn, md, mx, diff;
+	uint32_t i;
+
+	mn = mx = vpriv->framebuf[0].pts;
+	for(i = 0; i < 3; i++) 
+	{
+		mp_msg(MSGT_DECVIDEO,MSGL_V, "PTS: %llu\n", vpriv->framebuf[i].pts);
+		if(vpriv->framebuf[i].pts < mn)
+			mn = vpriv->framebuf[i].pts;
+		if(vpriv->framebuf[i].pts > mx)
+			mx = vpriv->framebuf[i].pts;
+	}
+	md = mn;
+	for(i=0; i<3; i++) 
+	{
+		if((vpriv->framebuf[i].pts > mn) && (vpriv->framebuf[i].pts < mx))
+		md = vpriv->framebuf[i].pts;
+	}
+	mp_msg(MSGT_DECVIDEO,MSGL_V, "MIN: %llu, mid: %llu, max: %llu\n", mn, md, mx);
+	
+	if(mx - md > md - mn)
+		diff = md - mn;
+	else
+		diff = mx - md;
+
+	if(diff > 0)
+	{
+		for(i=0; i<3; i++) 
+		{
+			vpriv->framebuf[i].pts += diff;
+			vpriv->framebuf[i].dts += i * diff;
+			mp_msg(MSGT_MUXER, MSGL_V, "FIXED_PTS: %.3lf, FIXED_DTS: %.3lf\n", 
+				(double) (vpriv->framebuf[i].pts/92160000.0), (double) (vpriv->framebuf[i].dts/92160000.0));
+		}
+		return diff;
+	}
+	else
+		return 0;
+}
+
+
+static size_t parse_mpeg4_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_headers_t *vpriv, float fps, size_t len)
+{
+	size_t ptr = 0;
+	int64_t delta_pts;
+	uint8_t pt;
+	
+	mp_msg(MSGT_MUXER, MSGL_V,"parse_mpeg4_video, len=%u\n", (uint32_t) len);
+	if(len<6) 
+	{
+		mp_msg(MSGT_MUXER, MSGL_ERR,"Frame too short: %d, exit!\n", len);
+		return 0;
+	}
+	
+	while(ptr < len - 5)
+	{
+		if(s->buffer[ptr] != 0 || s->buffer[ptr+1] != 0 || s->buffer[ptr+2] != 1)
+		{
+			ptr++;
+			continue;
+		}
+		
+		if(s->buffer[ptr+3] >= 0x20 && s->buffer[ptr+3] <= 0x2f) //VOL
+		{
+			mp4_header_process_vol(&(vpriv->picture), &(s->buffer[ptr+4]));
+		}
+		else if(s->buffer[ptr+3] == 0xb3)	//gov
+		{
+			//fprintf(stderr, "\nGOV\n");
+		}
+		else if(s->buffer[ptr+3] == 0xb6)	//vop
+		{
+			int32_t delta;
+			mp4_header_process_vop(&(vpriv->picture), &(s->buffer[ptr+4]));
+			
+			delta = vpriv->picture.timeinc_unit - vpriv->last_tr;
+			if((delta > 0) && (delta > (vpriv->picture.timeinc_resolution/2)))
+				delta -= vpriv->picture.timeinc_resolution;
+			else if((delta < 0) && (delta < (-vpriv->picture.timeinc_resolution/2)))
+				delta += vpriv->picture.timeinc_resolution;
+			
+			delta_pts = (92160000 * (int64_t) delta) / vpriv->picture.timeinc_resolution;
+			
+			pt = vpriv->picture.picture_type + 1;
+			mp_msg(MSGT_MUXER, MSGL_V, "\nTYPE: %c, RESOLUTION: %d, TEMP: %d, delta: %d, delta_pts: %lld = %.3lf, delta2: %.3lf\n", 
+				FTYPE(pt), vpriv->picture.timeinc_resolution, vpriv->picture.timeinc_unit, delta, delta_pts, (double) (delta_pts/92160000.0),
+				(double) delta / (double) vpriv->picture.timeinc_resolution);
+			
+			vpriv->last_tr = vpriv->picture.timeinc_unit;	
+			
+			break;
+		}
+		
+		ptr++;
+	}
+	
+	vpriv->last_dts += vpriv->frame_duration;
+	vpriv->last_pts += delta_pts;
+	
+	reorder_frame(vpriv, s->buffer, len, pt, 0, delta_pts);
+	vpriv->framebuf[vpriv->framebuf_used-1].pts = vpriv->last_pts;
+	vpriv->framebuf[vpriv->framebuf_used-1].dts = vpriv->last_dts;
+	vpriv->framebuf[vpriv->framebuf_used-1].idur = vpriv->frame_duration;
+	
+	/*mp_msg(MSGT_MUXER, MSGL_V, "\nMPEG4V, PT: %c, LEN=%u, DELTA_PTS: %.3lf, PTS: %.3lf, DTS: %.3lf\n", 
+		FTYPE(pt), len, (delta_pts/92160000.0),
+		(double) (vpriv->framebuf[vpriv->framebuf_used-1].pts/92160000.0), 
+		(double) (vpriv->framebuf[vpriv->framebuf_used-1].dts/92160000.0), len);*/
+	
+	if(!vpriv->frame_duration && vpriv->framebuf_used == 3)
+	{
+		vpriv->frame_duration = fix_mp4_frame_duration(vpriv);
+		if(vpriv->frame_duration)
+		{
+			vpriv->last_pts += vpriv->frame_duration;
+			vpriv->last_dts = vpriv->framebuf[vpriv->framebuf_used-1].dts;
+			vpriv->delta_clock = ((double) vpriv->frame_duration)/92160000.0;
+			mp_msg(MSGT_MUXER, MSGL_INFO, "FRAME DURATION: %llu   %.3lf\n", 
+				vpriv->frame_duration, (double) (vpriv->frame_duration/92160000.0));
+		}
+	}
+	
+	mp_msg(MSGT_MUXER, MSGL_V, "LAST_PTS: %.3lf, LAST_DTS: %.3lf\n", 
+		(double) (vpriv->last_pts/92160000.0), (double) (vpriv->last_dts/92160000.0));
+	
+	return len;
 }
 
 static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags){
-  size_t ptr=0, sz;
-  unsigned int pts=0;
+  size_t ptr=0, sz = 0;
+  uint64_t pts, tmp;
   muxer_t *muxer = s->muxer;
+  muxer_priv_t *priv = (muxer_priv_t *)muxer->priv;
+  muxer_headers_t *spriv = (muxer_headers_t*) s->priv;
   FILE *f;
-
+  float fps;
+  uint32_t stream_format;
+  
   f = muxer->file;
+ 
+  if(s->buffer == NULL)
+  	return;
+  
+  pts = 0;
   if (s->type == MUXER_TYPE_VIDEO) { // try to recognize frame type...
-    if (s->buffer[0] != 0 || s->buffer[1] != 0 || s->buffer[2] != 1 || len<6) {
-      printf ("Unknown block type, possibly non-MPEG stream!\n");
-      sz = len;
-//      return;
-    } else if (s->buffer[3] == 0 || s->buffer[3] == 0xb3 ||
-	       s->buffer[3] == 0xb8) { // Picture or GOP
-      int temp_ref;
-      int pt;
+	fps = (float) s->h.dwRate/ (float) s->h.dwScale;
+  	spriv->type = 1;
+	spriv->has_pes_priv_headers = 0;
+	stream_format = s->bih->biCompression;
 
-      if (s->buffer[3]) { // GOP -- scan for Picture
-	s->gop_start = s->h.dwLength;
-	while (ptr < len-5 && (s->buffer[ptr] != 0 || s->buffer[ptr+1] != 0 ||
-	       s->buffer[ptr+2] != 1 || s->buffer[ptr+3] != 0)) ptr++;
-	if (s->b_buffer_ptr > MUXER_MPEG_DATASIZE-39-12) { // 39 bytes for Gop+Pic+Slice headers
-	  write_mpeg_block (muxer, s, f, NULL, 0, 0);
-	}
-      }
-      if (ptr >= len-5) {
-	pt = 0; // Picture not found?!
-	temp_ref = 0;
-	printf ("Warning: picture not found in GOP!\n");
-      } else {
-	pt = (s->buffer[ptr+5]>>3) & 7;
-	temp_ref = (s->buffer[ptr+4]<<2)+(s->buffer[ptr+5]>>6);
+    if(is_mpeg1(stream_format) || is_mpeg2(stream_format))
+    {
+      spriv->is_mpeg12 = 1;
+      if(len)
+        sz = parse_mpeg12_video(s, priv, spriv, fps, len);
+      else {
+        tmp = (uint64_t) (92160000 / fps);
+        spriv->last_pts += tmp;
+        spriv->last_dts += tmp;
       }
-      ptr = 0;
-      temp_ref += s->gop_start;
-      switch (pt) {
-	case 2: // predictive
-	  if (s->ipb[0]) {
-	    sz = len + s->ipb[0];
-	    if (s->ipb[0] < s->ipb[2])
-	      s->ipb[0] = s->ipb[2];
-	    s->ipb[2] = 0;
-	  } else if (s->ipb[2]) {
-	    sz = len + s->ipb[2];
-	    s->ipb[0] = s->ipb[2];
-	    s->ipb[2] = 0;
-	  } else
-	    sz = 4 * len; // no bidirectional frames yet?
-	  s->ipb[1] = len;
-	  // pictires may be not in frame sequence so recalculate timer
-	  pts = (int)(90000*((double)temp_ref*s->h.dwScale/s->h.dwRate)) + MPEG_STARTPTS;
-	  break;
-	case 3: // bidirectional
-	  s->ipb[2] += len;
-	  sz = s->ipb[1] + s->ipb[2];
-	  // pictires may be not in frame sequence so recalculate timer
-	  s->timer = (double)temp_ref*s->h.dwScale/s->h.dwRate;
-	  break;
-	default: // intra-coded
-	  // pictires may be not in frame sequence so recalculate timer
-	  pts = (int)(90000*((double)temp_ref*s->h.dwScale/s->h.dwRate)) + MPEG_STARTPTS;
-	  sz = len; // no extra buffer for it...
+    }
+    else if(is_mpeg4(stream_format)) 
+    {
+      spriv->is_mpeg12 = 0;
+      spriv->reorder = 0;
+      if(spriv->size == 0)
+        priv->use_psm = 1;
+      if(len)
+        sz = parse_mpeg4_video(s, priv, spriv, fps, len);
+      else {
+        tmp = (uint64_t) (92160000 / fps);
+        spriv->last_pts += tmp;
+        spriv->last_dts += tmp;
       }
-    } else {
-      printf ("Unknown block type, possibly non-MPEG stream!\n");
-      sz = len;
-//      return;
     }
+
+    mp_msg(MSGT_MUXER, MSGL_V,"mpegfile_write_chunk, Video codec=%x, len=%u, mpeg12 returned %u\n", stream_format, (uint32_t) len, (uint32_t) sz);
+
+    ptr = 0;
+    priv->vbytes += len;
+    
     sz <<= 1;
   } else { // MUXER_TYPE_AUDIO
-    if (len < 2*MUXER_MPEG_DATASIZE)
-      sz = 2*MUXER_MPEG_DATASIZE; // min requirement
-    else
-      sz = len;
-  }
-  mp_dbg(MSGT_MUXER, MSGL_DBG3, "\nMPEG chunk: size=%u, pts=%f", len, s->timer);
-  set_mpeg_pts (muxer, s, pts);
-  // alter counters:
-  if (s->h.dwSampleSize) {
-    // CBR
-    s->h.dwLength += len/s->h.dwSampleSize;
-    if (len%s->h.dwSampleSize) printf("Warning! len isn't divisable by samplesize!\n");
-  } else {
-    // VBR
-    s->h.dwLength++;
-  }
-  if (!muxer->sysrate) {
-    muxer->sysrate = 2108000/8; // constrained stream parameter
-    muxer->file_end = MUXER_MPEG_BLOCKSIZE*90000/muxer->sysrate + MPEG_STARTSCR+1;
+  	spriv->type = 0;
+	stream_format = s->wf->wFormatTag;
+	
+		mp_msg(MSGT_MUXER, MSGL_V,"\nmpegfile_write_chunk, Audio codec=%x, len=%u, frame size=%u\n", 
+			stream_format, (uint32_t) len, (uint32_t) spriv->frame_size);
+	if(spriv->bitrate == 0)
+		spriv->bitrate = s->wf->nAvgBytesPerSec;
+	// I need to know the audio frame size
+	if(spriv->frame_size == 0)
+	{
+		spriv->frame_size = get_audio_frame_size(spriv, s->buffer, stream_format, s->wf->nSamplesPerSec);
+		spriv->aframe_delta_pts = ((double) spriv->frame_size / (double) spriv->bitrate);
+		//spriv->delta_pts = (uint64_t) (spriv->aframe_delta_pts * 92160000);
+		spriv->delta_pts = (uint64_t) (92160000 * spriv->frame_size) / spriv->bitrate;
+		mp_msg(MSGT_MUXER, MSGL_INFO, "AUDIO FRAME SIZE: %u, DELTA_PTS: %llu (%.3lf)\n", (uint32_t) spriv->frame_size, spriv->delta_pts, spriv->aframe_delta_pts);
+	}
+	
+		
+	if(s->b_buffer_size - s->b_buffer_len < len)
+	{
+		s->b_buffer = realloc(s->b_buffer, len  + s->b_buffer_len);
+		if(s->b_buffer == NULL)
+		{
+			mp_msg(MSGT_MUXER, MSGL_FATAL, "\nFATAL! couldn't realloc %d bytes\n", len  + s->b_buffer_len);
+			return;
+		}
+		
+		s->b_buffer_size = len  + s->b_buffer_len;
+		mp_msg(MSGT_MUXER, MSGL_DBG2, "REALLOC(%d) bytes to AUDIO backbuffer\n", s->b_buffer_size);
+	}
+	memcpy(&(s->b_buffer[s->b_buffer_ptr + s->b_buffer_len]), s->buffer, len);
+	s->b_buffer_len += len;
+	
+	if(stream_format == AUDIO_A52)
+	{
+		s->type = 1;
+		s->ckid = be2me_32 (0x1bd);
+		if(s->size == 0) 
+		{
+			spriv->max_pl_size -= 4;
+			if(priv->is_genmpeg1 || priv->is_genmpeg2)
+				fix_audio_sys_header(priv, spriv->id, 0xbd, 58*1024);	//only one audio at the moment
+			spriv->id = 0xbd;
+		}
+	}
+	
+	if(priv->init_adelay < 0)
+	{
+		uint64_t delay_len;
+		priv->abytes += len;
+		delay_len = (uint64_t) abs((priv->init_adelay * (double) spriv->bitrate));
+		if(priv->abytes >= delay_len)
+		{
+			if(priv->drop)
+			{
+				mp_msg(MSGT_MUXER, MSGL_V, "\nDROPPING %llu AUDIO BYTES, DELAY: %.3lf, BR: %u\n", delay_len, priv->init_adelay, spriv->bitrate);
+				drop_delayed_audio(muxer, s, (int64_t) delay_len);
+			}
+			else
+			{
+				mp_msg(MSGT_MUXER, MSGL_V, "\nWRITING %llu EARLY AUDIO BYTES, DELAY: %.3lf, BR: %u\n", delay_len, priv->init_adelay, spriv->bitrate);
+				save_delayed_audio(muxer, s, (uint64_t) (92160000 * (-priv->init_adelay)));
+			}
+			priv->init_adelay = 0.0;
+			conf_init_adelay = 0;
+			priv->drop = 0;
+		}
+	}
+	
+	sz = max(len, 2 * priv->packet_size);
   }
-  if (sz > s->h.dwSuggestedBufferSize) { // increase and set STD
-    s->h.dwSuggestedBufferSize = sz;
-    if (s->b_buffer[2] != 0xff) // has both PTS and DTS
-      write_mpeg_std (s->b_buffer, s->h.dwSuggestedBufferSize, 0x40); // 01
-    else // has only PTS
-      write_mpeg_std (s->b_buffer+5, s->h.dwSuggestedBufferSize, 0x40); // 01
+  
+  if (s->h.dwSampleSize) {
+	// CBR
+	s->h.dwLength += len/s->h.dwSampleSize;
+	if (len%s->h.dwSampleSize) mp_msg(MSGT_MUXER, MSGL_ERR, "Warning! len isn't divisable by samplesize!\n");
+  } else {
+	// VBR
+	s->h.dwLength++;
   }
+  
   s->size += len;
-  // write out block(s) if it's ready
-  while (s->b_buffer_ptr+len >= MUXER_MPEG_DATASIZE-12) { // reserved for std and pts
-    // write out the block
-    sz = write_mpeg_block (muxer, s, f, &s->buffer[ptr], len, 0);
-    // recalculate the rest of chunk
-    ptr += sz;
-    len -= sz;
+  s->timer = (double)s->h.dwLength*s->h.dwScale/s->h.dwRate;
+
+  //if genmpeg1/2 and sz > last buffer size in the system header we must write the new sysheader
+  if(sz > s->h.dwSuggestedBufferSize) { // increase and set STD 
+	s->h.dwSuggestedBufferSize = sz;
+	if(priv->is_genmpeg1 || priv->is_genmpeg2) {
+		fix_buffer_params(priv, spriv->id, s->h.dwSuggestedBufferSize);
+		priv->update_system_header = 1;
+	}
+  }
+  
+  if(spriv->psm_fixed == 0) {
+  	add_to_psm(priv, spriv->id, stream_format);
+	spriv->psm_fixed = 1;
+	priv->psm_streams_cnt++;
+	if((priv->psm_streams_cnt == muxer->num_videos + muxer->num_audios) && priv->use_psm)
+		write_psm_block(muxer, muxer->file);
   }
-  s->timer = (double)s->h.dwLength*s->h.dwScale/s->h.dwRate;
-  if (len) { // save rest in buffer
-    if (s->b_buffer_ptr == 0) {
-      memset (s->b_buffer, 0xff, 12); // stuFFing bytes for now
-      if (s->type == MUXER_TYPE_AUDIO && s->h.dwSampleSize) { // CBR audio
-	sz = s->h.dwLength - len/s->h.dwSampleSize; // first sample number
-	write_mpeg_ts (s->b_buffer+7,
-	    (int)(90000*((double)sz*s->h.dwScale/s->h.dwRate)) + MPEG_STARTPTS,
-	    0x20); // 0010 and PTS only
-      }
-      s->b_buffer_ptr = 12;
-    }
-    memcpy (s->b_buffer+s->b_buffer_ptr, s->buffer+ptr, len);
-    s->b_buffer_ptr += len;
-  }
-  mp_dbg(MSGT_MUXER, MSGL_DBG3, " next pts=%f\n", s->timer);
+  
+
+  if(priv->init_adelay != 0)
+    return;
+  
+  flush_buffers(muxer, 0);
+}
+
+
+static void mpegfile_write_index(muxer_t *muxer)
+{
+	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	while(flush_buffers(muxer, 0) > 0);
+	flush_buffers(muxer, 1);
+	if(priv->is_genmpeg1 || priv->is_genmpeg2)
+		write_mpeg_pack(muxer, NULL, muxer->file, NULL, 0, 1);	//insert fake Nav Packet
+		
+	mp_msg(MSGT_MUXER, MSGL_INFO, "\nOverhead: %.3lf%% (%llu / %llu)\n", 100.0 * (double)priv->headers_size / (double)priv->data_size, priv->headers_size, priv->data_size);
+}
+
+static void mpegfile_write_header(muxer_t *muxer)
+{
+	muxer_priv_t *priv = (muxer_priv_t*) muxer->priv;
+	
+	priv->headers_cnt++;
+	
+	if((priv->is_genmpeg1 || priv->is_genmpeg2) && (priv->headers_cnt == muxer->avih.dwStreams))
+	{
+		int i;
+		for(i = 0; i < muxer->avih.dwStreams; i++)
+		{
+			priv->sys_info.streams[i].bufsize = muxer->streams[i]->h.dwSuggestedBufferSize;
+			mp_msg(MSGT_MUXER, MSGL_V, "IDX: %d, BUFSIZE: %u\n", i, priv->sys_info.streams[i].bufsize);
+		}
+	}
+	
+	//write the first system header only for generic mpeg1/2 muxes, and only when we have collected all necessary infos
+	if(priv->is_genmpeg1 || priv->is_genmpeg2 || ((priv->is_xvcd || priv->is_xsvcd) && (priv->headers_cnt == 1)))
+	{
+		write_mpeg_pack(muxer, NULL, muxer->file, NULL, 0, 0);
+		priv->update_system_header = 0;
+	}
+	
+	return;
 }
 
-static void mpegfile_write_header(muxer_t *muxer){
-  unsigned int i;
-  size_t sz = MUXER_MPEG_BLOCKSIZE-24;
-  unsigned char buff[12];
-  muxer_stream_t *s = muxer->streams[0];
-  uint32_t l1;
-  uint16_t l2;
-  FILE *f = muxer->file;
-
-  if (s == NULL)
-    return; // no streams!?
-  // packet header (0x1ba) -- rewrite first stream buffer
-  *(uint32_t *)buff = be2me_32 (0x1ba);
-  write_mpeg_ts (buff+4, MPEG_STARTSCR, 0x20); // 0010 -- pack
-  write_mpeg_rate (buff+9, muxer->sysrate);
-  fwrite (buff, 12, 1, f);
-  // start system stream (in own block): Sys (0x1bb)
-  l1 = be2me_32 (0x1bb);
-  l2 = be2me_16 (6 + 3*muxer->avih.dwStreams); // header_length
-  fwrite (&l1, 4, 1, f);
-  fwrite (&l2, 2, 1, f);
-  write_mpeg_rate (buff, muxer->sysrate); // rate_bound
-  // set number of audio/video, fixed_flag=CSPS_flag=system_*_lock_flag=0
-  buff[3] = (muxer->avih.dwStreams - muxer->num_videos) << 2; // audio_bound
-  buff[4] = muxer->num_videos | 0x20;
-  buff[5] = 0xff; // reserved_byte
-  fwrite (buff, 6, 1, f);
-  for (i = 0; i < muxer->avih.dwStreams; i++) {
-    buff[0] = ((char *)&muxer->streams[i]->ckid)[3]; // last char in big endian
-//fprintf (stderr, "... stream 0x1%02x; bufsize %u", (int)buff[0], muxer->streams[i]->h.dwSuggestedBufferSize);
-    write_mpeg_std (buff+1, muxer->streams[i]->h.dwSuggestedBufferSize, 0xc0); // 11
-    fwrite (buff, 3, 1, f);
-    sz -= 3;
-  }
-  if (sz >= 6) { // padding block
-    l1 = be2me_32 (0x1be);
-    sz -= 6;
-    l2 = be2me_16 (sz);
-    fwrite (&l1, 4, 1, f);
-    fwrite (&l2, 2, 1, f);
-  }
-  s->b_buffer[0] = 0x0f; // end of list - next bit has to be 0
-  // stuFFing bytes -- rewrite first stream buffer
-  if (sz > 1)
-    memset (s->b_buffer+1, 0xff, sz-1);
-  fwrite (s->b_buffer, sz, 1, f);
-  muxer->movi_start = 0;
-  muxer->movi_end = MUXER_MPEG_BLOCKSIZE;
+static void setup_sys_params(muxer_priv_t *priv)
+{
+	if(priv->is_dvd)
+	{
+		priv->sys_info.cnt = 4;
+		
+		priv->sys_info.streams[0].id = 0xb9;
+		priv->sys_info.streams[0].type = 1;
+		priv->sys_info.streams[0].bufsize = 232*1024;
+			
+		priv->sys_info.streams[1].id = 0xb8;
+		priv->sys_info.streams[1].type = 0;
+		priv->sys_info.streams[1].bufsize = 4*1024;
+		
+		priv->sys_info.streams[2].id = 0xbd;
+		priv->sys_info.streams[2].type = 1;
+		priv->sys_info.streams[2].bufsize = 58*1024;
+		
+		priv->sys_info.streams[3].id = 0xbf;
+		priv->sys_info.streams[3].type = 1;
+		priv->sys_info.streams[3].bufsize = 2*1024;
+	}
+	else if(priv->is_xvcd || priv->is_xsvcd)
+	{
+		priv->sys_info.cnt = 2;
+		
+		priv->sys_info.streams[0].id = 0xe0;
+		priv->sys_info.streams[0].type = 1;
+		priv->sys_info.streams[0].bufsize = (priv->is_xvcd ? 46: 230)*1024;
+			
+		priv->sys_info.streams[1].id = 0xc0;
+		priv->sys_info.streams[1].type = 0;
+		priv->sys_info.streams[1].bufsize = 4*1024;
+	}
+	else
+		priv->sys_info.cnt = 0;
 }
 
-static void mpegfile_write_index(muxer_t *muxer){
-  unsigned int i;
-  unsigned int rsr;
+
+int muxer_init_muxer_mpeg(muxer_t *muxer){
+  muxer_priv_t *priv;
+  priv = (muxer_priv_t *) calloc(1, sizeof(muxer_priv_t));
+  if(priv == NULL)
+  	return 0;
+  priv->update_system_header = 1;
+  
+  //calloc() already zero-ed all flags, so we assign only the ones we need
+  
+  if(conf_mux != NULL) {
+    if(! strcasecmp(conf_mux, "mpeg2"))
+    {
+    	priv->mux = MUX_MPEG2;
+	priv->packet_size = 2048;
+	priv->is_genmpeg2 = 1;
+	priv->muxrate = 1800 * 125;	//Constrained parameters
+    }
+    else if(! strcasecmp(conf_mux, "dvd"))
+    {
+	priv->mux = MUX_MPEG2;
+	priv->is_dvd = 1;
+	priv->packet_size = 2048;
+	priv->muxrate = 10080 * 125;
+    }
+    else if(! strcasecmp(conf_mux, "xsvcd"))
+    {
+	priv->mux = MUX_MPEG2;
+	priv->is_xsvcd = 1;
+	priv->packet_size = 2324;
+	//what's the right muxrate?
+	priv->muxrate = 2788 * 125;
+	priv->ts_allframes = 1;
+    }
+    else if(! strcasecmp(conf_mux, "xvcd"))
+    {
+	priv->mux = MUX_MPEG1;
+	priv->is_xvcd = 1;
+	priv->packet_size = 2324;
+	//what's the right muxrate?
+	priv->muxrate = 1394 * 125;
+	priv->ts_allframes = 1;
+    }
+    else
+    {
+	priv->mux = MUX_MPEG1;
+	priv->is_genmpeg1 = 1;
+	priv->packet_size = 2048;
+	priv->muxrate = 1800 * 125;	//Constrained parameters
+    }
+  }
+
+  if(conf_ts_allframes)
+  	priv->ts_allframes = 1;
+  if(conf_muxrate > 0)
+  	priv->muxrate = conf_muxrate * 125;		// * 1000 / 8
+  if(conf_packet_size)
+  	priv->packet_size = conf_packet_size;
+  mp_msg(MSGT_MUXER, MSGL_INFO, "PACKET SIZE: %u bytes\n", priv->packet_size);
+  setup_sys_params(priv);
 
-  if (!muxer->avih.dwStreams) return; // no streams?!
-  // finish all but one video and audio streams
-  rsr = muxer->sysrate; // reserve it since it's silly change it at that point
-  for (i = 0; i < muxer->avih.dwStreams-1; i++)
-    write_mpeg_block (muxer, muxer->streams[i], muxer->file, NULL, 0, 0);
-  // end sequence: ISO-11172-End (0x1b9) and finish very last block
-  write_mpeg_block (muxer, muxer->streams[i], muxer->file, NULL, 0, 1);
-//fprintf (stderr, "PTS to SCR delay: min %u.%03u, max %u.%03u\n",
-//	mpeg_min_delay/90000, (mpeg_min_delay/90)%1000,
-//	mpeg_max_delay/90000, (mpeg_max_delay/90)%1000);
-  muxer->sysrate = rsr;
-}
-
-void muxer_init_muxer_mpeg(muxer_t *muxer){
+  priv->skip_padding = conf_skip_padding;
+  if(conf_vaspect != NULL)
+  {
+	if(! strcmp(conf_vaspect, "1/1"))
+		priv->vaspect = ASPECT_1_1;
+	else if(! strcmp(conf_vaspect, "4/3"))
+		priv->vaspect = ASPECT_4_3;
+	else if(! strcmp(conf_vaspect, "16/9"))
+		priv->vaspect = ASPECT_16_9;
+	else if(! strcmp(conf_vaspect, "2.21/1"))
+		priv->vaspect = ASPECT_2_21_1;
+  }
+  
+  priv->vframerate = 0;		// no change
+  if(conf_vframerate != NULL)
+  {
+	if(! strcmp(conf_vframerate, "23.976"))
+		priv->vframerate = FRAMERATE_23976;
+	else if(! strcmp(conf_vframerate, "24"))
+		priv->vframerate = FRAMERATE_24;
+	else if(! strcmp(conf_vframerate, "25"))
+		priv->vframerate = FRAMERATE_25;
+	else if(! strcmp(conf_vframerate, "29.97"))
+		priv->vframerate = FRAMERATE_2997;
+	else if(! strcmp(conf_vframerate, "30"))
+		priv->vframerate = FRAMERATE_30;
+	else if(! strcmp(conf_vframerate, "50"))
+		priv->vframerate = FRAMERATE_50;
+	else if(! strcmp(conf_vframerate, "59.94"))
+		priv->vframerate = FRAMERATE_5994;
+	else if(! strcmp(conf_vframerate, "60"))
+		priv->vframerate = FRAMERATE_60;
+  }
+  
+  priv->vwidth = (uint16_t) conf_vwidth;
+  priv->vheight = (uint16_t) conf_vheight;
+  priv->panscan_width = (uint16_t) conf_panscan_width;
+  priv->panscan_height = (uint16_t) conf_panscan_height;
+  priv->vbitrate = ((conf_vbitrate) * 10) >> 2;	//*1000 / 400
+  
+  if(priv->vaspect || priv->vframerate || priv->vwidth || priv->vheight || priv->vbitrate || priv->panscan_width || priv->panscan_height)
+  {
+  	priv->patch_seq = priv->vaspect || priv->vframerate || priv->vwidth || priv->vheight || priv->vbitrate;
+	priv->patch_sde = priv->panscan_width || priv->panscan_height;
+	mp_msg(MSGT_MUXER, MSGL_INFO, "MPEG MUXER, patching");
+	if(priv->vwidth || priv->vheight)
+		mp_msg(MSGT_MUXER, MSGL_INFO, " resolution to %dx%d", priv->vwidth, priv->vheight);
+	if(priv->panscan_width || priv->panscan_height)
+		mp_msg(MSGT_MUXER, MSGL_INFO, " panscan to to %dx%d", priv->panscan_width, priv->panscan_height);
+	if(priv->vframerate)
+		mp_msg(MSGT_MUXER, MSGL_INFO, " framerate to %s fps", framerates[priv->vframerate]);
+	if(priv->vaspect)
+		mp_msg(MSGT_MUXER, MSGL_INFO, " aspect ratio to %s", aspect_ratios[priv->vaspect]);
+	if(priv->vbitrate)
+		mp_msg(MSGT_MUXER, MSGL_INFO, " bitrate to %u", conf_vbitrate);
+	mp_msg(MSGT_MUXER, MSGL_INFO, "\n");
+  }
+  
+  priv->has_video = priv->has_audio = 0;
+  
+  
+  muxer->sysrate = priv->muxrate; 		// initial muxrate = constrained stream parameter
+  priv->scr = muxer->file_end = 0;
+  
+  if(conf_init_adelay)
+  	priv->init_adelay = (double) conf_init_adelay / (double) 1000.0;
+  
+  priv->drop = conf_drop;
+  
+  priv->buff = (uint8_t *) malloc(priv->packet_size);
+  priv->tmp = (uint8_t *) malloc(priv->packet_size);
+  priv->residual = (uint8_t *) malloc(priv->packet_size);
+  if((priv->buff == NULL) || (priv->tmp == NULL) || (priv->residual == NULL))
+  {
+	mp_msg(MSGT_MUXER, MSGL_ERR, "\nCouldn't allocate %d bytes, exit\n", priv->packet_size);
+	return 0;
+  }
+  
+  muxer->priv = (void *) priv;
   muxer->cont_new_stream = &mpegfile_new_stream;
   muxer->cont_write_chunk = &mpegfile_write_chunk;
   muxer->cont_write_header = &mpegfile_write_header;
   muxer->cont_write_index = &mpegfile_write_index;
-//  mpeg_min_delay = mpeg_max_delay = MPEG_STARTPTS-MPEG_STARTSCR;
+  return 1;
 }
 
--- a/libmpdemux/muxer_rawvideo.c	Mon Feb 21 17:40:46 2005 +0000
+++ b/libmpdemux/muxer_rawvideo.c	Mon Feb 21 21:45:49 2005 +0000
@@ -90,9 +90,10 @@
     return;
 }
 
-void muxer_init_muxer_rawvideo(muxer_t *muxer){
+int muxer_init_muxer_rawvideo(muxer_t *muxer){
   muxer->cont_new_stream = &rawvideofile_new_stream;
   muxer->cont_write_chunk = &rawvideofile_write_chunk;
   muxer->cont_write_header = &rawvideofile_write_header;
   muxer->cont_write_index = &rawvideofile_write_index;
+  return 1;
 }