[Mplayer-cvslog] CVS: main/libmpdemux muxer.c,NONE,1.1 muxer_mpeg.c,NONE,1.1 Makefile,1.44,1.45 muxer.h,1.5,1.6 muxer_avi.c,1.12,1.13 aviwrite.c,1.12,NONE aviwrite.h,1.5,NONE

Arpi of Ize arpi at mplayerhq.hu
Fri Dec 27 23:43:24 CET 2002


Update of /cvsroot/mplayer/main/libmpdemux
In directory mail:/var/tmp.root/cvs-serv25481/libmpdemux

Modified Files:
	Makefile muxer.h muxer_avi.c 
Added Files:
	muxer.c muxer_mpeg.c 
Removed Files:
	aviwrite.c aviwrite.h 
Log Message:
the long-waited MUXER layer, and new MPEG-PS muxer
patch by Andriy N. Gritsenko <andrej at lucky.net>


--- NEW FILE ---

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include "config.h"
#include "../version.h"

#include "wine/mmreg.h"
#include "wine/avifmt.h"
#include "wine/vfw.h"

#include "muxer.h"

muxer_t* muxer_new_muxer(int type){
    muxer_t* muxer=malloc(sizeof(muxer_t));
    memset(muxer,0,sizeof(muxer_t));
    switch (type) {
      case MUXER_TYPE_MPEG:
	muxer_init_muxer_mpeg(muxer);
	break;
      case MUXER_TYPE_AVI:
      default:
	muxer_init_muxer_avi(muxer);
    }
    return muxer;
}

--- NEW FILE ---

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include "config.h"
#include "../version.h"

#include "wine/mmreg.h"
#include "wine/avifmt.h"
#include "wine/vfw.h"
#include "bswap.h"

#include "muxer.h"

// 18 bytes reserved for block headers and STD
#define MUXER_MPEG_DATASIZE (MUXER_MPEG_BLOCKSIZE-18)

// ISO-11172 requirements
#define MPEG_MAX_PTS_DELAY 90000 /* 1s */
#define MPEG_MAX_SCR_INTERVAL 63000 /* 0.7s */

// suggestions
#define MPEG_STARTPTS 45000 /* 0.5s */
#define MPEG_MIN_PTS_DELAY 9000 /* 0.1s */
#define MPEG_STARTSCR 9 /* 0.1ms */

//static unsigned int mpeg_min_delay;
//static unsigned int mpeg_max_delay;

static muxer_stream_t* mpegfile_new_stream(muxer_t *muxer,int type){
  muxer_stream_t *s;

  if(muxer->avih.dwStreams>=MUXER_MAX_STREAMS){
    printf("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");
	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");
	return NULL;
      }
      break;
    default:
      printf ("Unknown stream type!\n");
      return NULL;
  }
  s=malloc(sizeof(muxer_stream_t));
  memset(s,0,sizeof(muxer_stream_t));
  if(!s) return NULL; // no mem!?
  if (!(s->b_buffer = malloc (MUXER_MPEG_BLOCKSIZE))) {
    free (s);
    return NULL; // no mem?!
  } else if (type == MUXER_TYPE_VIDEO) {
    s->ckid = be2me_32 (0x1e0 + muxer->num_videos);
    muxer->num_videos++;
    s->h.fccType=streamtypeVIDEO;
    if(!muxer->def_v) muxer->def_v=s;
//    printf ("Added video stream %d\n", muxer->num_videos);
  } else { // MUXER_TYPE_AUDIO
    s->ckid = be2me_32 (0x1c0 + s->id - muxer->num_videos);
    s->h.fccType=streamtypeAUDIO;
//    printf ("Added audio stream %d\n", s->id - muxer->num_videos + 1);
  }
  muxer->streams[muxer->avih.dwStreams]=s;
  s->type=type;
  s->id=muxer->avih.dwStreams;
  s->timer=0.0;
  s->size=0;
  muxer->avih.dwStreams++;
  return s;
}

static void write_mpeg_ts(unsigned char *b, unsigned int ts, char mod) {
  b[0] = ((ts >> 29) & 0xf) | 1 | mod;
  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_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_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;

  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;

    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 (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 set_mpeg_pts(muxer_t *muxer, muxer_stream_t *s, unsigned int pts) {
  unsigned int dts, nts;

  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 :)
  write_mpeg_ts (s->b_buffer+7, dts, 0x10);
}

static void mpegfile_write_chunk(muxer_t *muxer,muxer_stream_t *s,FILE *f,size_t len,unsigned int flags){
  size_t ptr=0, sz;
  unsigned int 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;

      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);
      }
      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 {
      printf ("Unknown block type, possibly non-MPEG stream!\n");
      sz = len;
//      return;
    }
    sz <<= 1;
  } else { // MUXER_TYPE_AUDIO
    if (len < 2*MUXER_MPEG_DATASIZE)
      sz = 2*MUXER_MPEG_DATASIZE; // min requirement
    else
      sz = len;
  }
  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;
  }
  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
  }
  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 (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;
  }
}

static void mpegfile_write_header(muxer_t *muxer,FILE *f){
  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;

  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 mpegfile_write_index(muxer_t *muxer,FILE *f){
  unsigned int i;
  unsigned int rsr;

  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], f, NULL, 0, 0);
  // end sequence: ISO-11172-End (0x1b9) and finish very last block
  write_mpeg_block (muxer, muxer->streams[i], f, 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){
  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;
}


Index: Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/Makefile,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -r1.44 -r1.45
--- Makefile	26 Dec 2002 17:25:22 -0000	1.44
+++ Makefile	27 Dec 2002 22:43:20 -0000	1.45
@@ -3,7 +3,7 @@
 
 include ../config.mak
 
-SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c parse_mp4.c demux_mpg.c demux_pva.c demux_viv.c demuxer.c dvdauth.c dvdnav_stream.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c demux_ogg.c demux_bmp.c cdda.c demux_rawaudio.c cddb.c cdinfo.c demux_rawdv.c ai_alsa.c ai_oss.c audio_in.c demux_smjpeg.c
+SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c muxer.c muxer_avi.c muxer_mpeg.c demux_asf.c demux_avi.c demux_mov.c parse_mp4.c demux_mpg.c demux_pva.c demux_viv.c demuxer.c dvdauth.c dvdnav_stream.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c demux_ogg.c demux_bmp.c cdda.c demux_rawaudio.c cddb.c cdinfo.c demux_rawdv.c ai_alsa.c ai_oss.c audio_in.c demux_smjpeg.c
 ifeq ($(XMMS_PLUGINS),yes)
 SRCS += demux_xmms.c
 endif 

Index: muxer.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/muxer.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- muxer.h	29 Aug 2002 20:50:49 -0000	1.5
+++ muxer.h	27 Dec 2002 22:43:20 -0000	1.6
@@ -1,20 +1,28 @@
 
-#define AVIWRITE_MAX_STREAMS 16
+#define MUXER_MAX_STREAMS 16
 
-#define AVIWRITE_TYPE_VIDEO 0
-#define AVIWRITE_TYPE_AUDIO 1
+#define MUXER_TYPE_VIDEO 0
+#define MUXER_TYPE_AUDIO 1
+
+#define MUXER_TYPE_AVI 0
+#define MUXER_TYPE_MPEG 1
+
+#define MUXER_MPEG_BLOCKSIZE 2048	// 2048 or 2324 - ?
 
 typedef struct {
   // muxer data:
   int type;  // audio or video
   int id;    // stream no
-  unsigned int ckid; // chunk id (00dc 01wb etc)
+  uint32_t ckid; // chunk id (00dc 01wb etc)
   double timer;
   off_t size;
   // buffering:
   unsigned char *buffer;
   unsigned int buffer_size;
   unsigned int buffer_len;
+  // mpeg block buffer:
+  unsigned char *b_buffer;
+  unsigned int b_buffer_ptr;
   // source stream:
   void* source; // sh_audio or sh_video
   int codec; // codec used for encoding. 0 means copy
@@ -23,34 +31,44 @@
   // stream specific:
   WAVEFORMATEX *wf;
   BITMAPINFOHEADER *bih;   // in format
-} aviwrite_stream_t;
+  // mpeg specific:
+  unsigned int gop_start; // frame number of this GOP start
+  size_t ipb[3]; // sizes of I/P/B frames
+} muxer_stream_t;
 
 typedef struct {
-  unsigned int id;
+  uint32_t id;
   char *text;
-} aviwrite_info_t;
+} muxer_info_t;
 
-typedef struct {
+typedef struct muxer_t{
   // encoding:
   MainAVIHeader avih;
   unsigned int movi_start;
   unsigned int movi_end;
-  unsigned int file_end;
+  unsigned int file_end; // for MPEG it's system timestamp in 1/90000 s
   // index:
   AVIINDEXENTRY *idx;
   int idx_pos;
   int idx_size;
   // streams:
+  int num_videos;	// for MPEG recalculations
+  unsigned int sysrate;	// max rate in bytes/s
   //int num_streams;
-  aviwrite_stream_t* def_v;  // default video stream (for general headers)
-  aviwrite_stream_t* streams[AVIWRITE_MAX_STREAMS];
-} aviwrite_t;
-
-aviwrite_stream_t* aviwrite_new_stream(aviwrite_t *muxer,int type);
-aviwrite_t* aviwrite_new_muxer();
-void aviwrite_write_chunk(aviwrite_t *muxer,aviwrite_stream_t *s, FILE *f,int len,unsigned int flags);
-void aviwrite_write_header(aviwrite_t *muxer,FILE *f);
-void aviwrite_write_index(aviwrite_t *muxer,FILE *f);
-
+  muxer_stream_t* def_v;  // default video stream (for general headers)
+  muxer_stream_t* streams[MUXER_MAX_STREAMS];
+  void (*cont_write_chunk)(struct muxer_t *,muxer_stream_t *,FILE *,size_t,unsigned int);
+  void (*cont_write_header)(struct muxer_t *,FILE *);
+  void (*cont_write_index)(struct muxer_t *,FILE *);
+  muxer_stream_t* (*cont_new_stream)(struct muxer_t *,int);
+} muxer_t;
+
+muxer_t* muxer_new_muxer(int type);
+#define muxer_new_stream(muxer,a) muxer->cont_new_stream(muxer,a)
+#define muxer_write_chunk(muxer,a,b,c,d) muxer->cont_write_chunk(muxer,a,b,c,d)
+#define muxer_write_header(muxer,f) muxer->cont_write_header(muxer,f)
+#define muxer_write_index(muxer,f) muxer->cont_write_index(muxer,f)
 
+void muxer_init_muxer_avi(muxer_t *);
+void muxer_init_muxer_mpeg(muxer_t *);
 

Index: muxer_avi.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_avi.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- muxer_avi.c	3 Nov 2002 09:51:06 -0000	1.12
+++ muxer_avi.c	27 Dec 2002 22:43:20 -0000	1.13
@@ -2,7 +2,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
+#include <inttypes.h>
 
 #include "config.h"
 #include "../version.h"
@@ -16,7 +16,7 @@
 #include "wine/vfw.h"
 #include "bswap.h"
 
-#include "aviwrite.h"
+#include "muxer.h"
 #include "aviheader.h"
 
 extern char *info_name;
@@ -27,14 +27,14 @@
 extern char *info_sourceform;
 extern char *info_comment;
 
-aviwrite_stream_t* aviwrite_new_stream(aviwrite_t *muxer,int type){
-    aviwrite_stream_t* s;
-    if(muxer->avih.dwStreams>=AVIWRITE_MAX_STREAMS){
-	printf("Too many streams! increase AVIWRITE_MAX_STREAMS !\n");
+static muxer_stream_t* avifile_new_stream(muxer_t *muxer,int type){
+    muxer_stream_t* s;
+    if(muxer->avih.dwStreams>=MUXER_MAX_STREAMS){
+	printf("Too many streams! increase MUXER_MAX_STREAMS !\n");
 	return NULL;
     }
-    s=malloc(sizeof(aviwrite_stream_t));
-    memset(s,0,sizeof(aviwrite_stream_t));
+    s=malloc(sizeof(muxer_stream_t));
+    memset(s,0,sizeof(muxer_stream_t));
     if(!s) return NULL; // no mem!?
     muxer->streams[muxer->avih.dwStreams]=s;
     s->type=type;
@@ -42,12 +42,12 @@
     s->timer=0.0;
     s->size=0;
     switch(type){
-    case AVIWRITE_TYPE_VIDEO:
+    case MUXER_TYPE_VIDEO:
       s->ckid=mmioFOURCC(('0'+s->id/10),('0'+(s->id%10)),'d','c');
       s->h.fccType=streamtypeVIDEO;
       if(!muxer->def_v) muxer->def_v=s;
       break;
-    case AVIWRITE_TYPE_AUDIO:
+    case MUXER_TYPE_AUDIO:
       s->ckid=mmioFOURCC(('0'+s->id/10),('0'+(s->id%10)),'w','b');
       s->h.fccType=streamtypeAUDIO;
       break;
@@ -59,12 +59,6 @@
     return s;
 }
 
-aviwrite_t* aviwrite_new_muxer(){
-    aviwrite_t* muxer=malloc(sizeof(aviwrite_t));
-    memset(muxer,0,sizeof(aviwrite_t));
-    return muxer;
-}
-
 static void write_avi_chunk(FILE *f,unsigned int id,int len,void* data){
  int le_len = le2me_32(len);
  int le_id = le2me_32(id);
@@ -93,7 +87,7 @@
 }
 }
 
-void aviwrite_write_chunk(aviwrite_t *muxer,aviwrite_stream_t *s, FILE *f,int len,unsigned int flags){
+static void avifile_write_chunk(muxer_t *muxer,muxer_stream_t *s, FILE *f,size_t len,unsigned int flags){
 
     // add to the index:
     if(muxer->idx_pos>=muxer->idx_size){
@@ -120,7 +114,7 @@
     }
     s->timer=(double)s->h.dwLength*s->h.dwScale/s->h.dwRate;
     s->size+=len;
-    if(len>s->h.dwSuggestedBufferSize) s->h.dwSuggestedBufferSize=len;
+    if((unsigned int)len>s->h.dwSuggestedBufferSize) s->h.dwSuggestedBufferSize=len;
 
 }
 
@@ -140,11 +134,11 @@
 // muxer->streams[i]->wf->cbSize
 #define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(((wf)->cbSize)?((wf)->cbSize-2):0))
 
-void aviwrite_write_header(aviwrite_t *muxer,FILE *f){
-  unsigned int riff[3];
-  int i;
+static void avifile_write_header(muxer_t *muxer,FILE *f){
+  uint32_t riff[3];
+  unsigned int i;
   unsigned int hdrsize;
-  aviwrite_info_t info[16];
+  muxer_info_t info[16];
 
   // RIFF header:
   riff[0]=mmioFOURCC('R','I','F','F');
@@ -173,10 +167,10 @@
       hdrsize+=12; // LIST
       hdrsize+=sizeof(muxer->streams[i]->h)+8; // strh
       switch(muxer->streams[i]->type){
-      case AVIWRITE_TYPE_VIDEO:
+      case MUXER_TYPE_VIDEO:
           hdrsize+=muxer->streams[i]->bih->biSize+8; // strf
 	  break;
-      case AVIWRITE_TYPE_AUDIO:
+      case MUXER_TYPE_AUDIO:
           hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf
 	  break;
       }
@@ -191,10 +185,10 @@
   for(i=0;i<muxer->avih.dwStreams;i++){
       hdrsize=sizeof(muxer->streams[i]->h)+8; // strh
       switch(muxer->streams[i]->type){
-      case AVIWRITE_TYPE_VIDEO:
+      case MUXER_TYPE_VIDEO:
           hdrsize+=muxer->streams[i]->bih->biSize+8; // strf
 	  break;
-      case AVIWRITE_TYPE_AUDIO:
+      case MUXER_TYPE_AUDIO:
           hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf
 	  break;
       }
@@ -204,7 +198,7 @@
       le2me_AVIStreamHeader(&muxer->streams[i]->h);
 
       switch(muxer->streams[i]->type){
-      case AVIWRITE_TYPE_VIDEO:
+      case MUXER_TYPE_VIDEO:
 {
           int biSize=muxer->streams[i]->bih->biSize;
           le2me_BITMAPINFOHEADER(muxer->streams[i]->bih);
@@ -212,7 +206,7 @@
           le2me_BITMAPINFOHEADER(muxer->streams[i]->bih);
 }
 	  break;
-      case AVIWRITE_TYPE_AUDIO:
+      case MUXER_TYPE_AUDIO:
 {
           int wfsize = WFSIZE(muxer->streams[i]->wf);
           le2me_WAVEFORMATEX(muxer->streams[i]->wf);
@@ -280,7 +274,7 @@
   muxer->movi_start=ftell(f);
 }
 
-void aviwrite_write_index(aviwrite_t *muxer,FILE *f){
+static void avifile_write_index(muxer_t *muxer,FILE *f){
   muxer->movi_end=ftell(f);
   if(muxer->idx && muxer->idx_pos>0){
       int i;
@@ -295,3 +289,9 @@
   muxer->file_end=ftell(f);
 }
 
+void 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;
+}

--- aviwrite.c DELETED ---

--- aviwrite.h DELETED ---




More information about the MPlayer-cvslog mailing list