summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-12-27 22:43:20 +0000
committerarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-12-27 22:43:20 +0000
commitbf46a109ede5d25f506cc75ae80fe1acc5b34edd (patch)
treea2cd8454df8950c0ab1ced5add63f293ea35d242
parentbc9afe8d39c9e12596677be1141f8098fec73db6 (diff)
downloadmpv-bf46a109ede5d25f506cc75ae80fe1acc5b34edd.tar.bz2
mpv-bf46a109ede5d25f506cc75ae80fe1acc5b34edd.tar.xz
the long-waited MUXER layer, and new MPEG-PS muxer
patch by Andriy N. Gritsenko <andrej@lucky.net> git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8586 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r--TOOLS/vivodump.c14
-rw-r--r--cfg-mencoder.h13
-rw-r--r--libmpcodecs/ve_divx4.c8
-rw-r--r--libmpcodecs/ve_lavc.c8
-rw-r--r--libmpcodecs/ve_libdv.c8
-rw-r--r--libmpcodecs/ve_qtvideo.c8
-rw-r--r--libmpcodecs/ve_rawrgb.c8
-rw-r--r--libmpcodecs/ve_vfw.c11
-rw-r--r--libmpcodecs/ve_xvid.c8
-rw-r--r--libmpdemux/Makefile2
-rw-r--r--libmpdemux/aviwrite.h56
-rw-r--r--libmpdemux/muxer.c28
-rw-r--r--libmpdemux/muxer.h74
-rw-r--r--libmpdemux/muxer_avi.c (renamed from libmpdemux/aviwrite.c)58
-rw-r--r--libmpdemux/muxer_mpeg.c434
-rw-r--r--mencoder.c48
16 files changed, 647 insertions, 139 deletions
diff --git a/TOOLS/vivodump.c b/TOOLS/vivodump.c
index c0c3417392..57205fd787 100644
--- a/TOOLS/vivodump.c
+++ b/TOOLS/vivodump.c
@@ -6,7 +6,7 @@
#include "wine/avifmt.h"
#include "wine/vfw.h"
-#include "aviwrite.h"
+#include "muxer.h"
static const short h263_format[8][2] = {
{ 0, 0 },
@@ -149,8 +149,8 @@ int pos=0;
int frames=0;
FILE *f=fopen("paulvandykforanangel.viv","rb");
FILE *f2=fopen("GB1.avi","wb");
-aviwrite_t* avi=aviwrite_new_muxer();
-aviwrite_stream_t* mux=aviwrite_new_stream(avi,AVIWRITE_TYPE_VIDEO);
+muxer_t* avi=muxer_new_muxer(MUXER_TYPE_AVI);
+muxer_stream_t* mux=muxer_new_stream(avi,MUXER_TYPE_VIDEO);
//unsigned char* buffer=malloc(0x200000);
int i,len;
int v_id=0;
@@ -169,7 +169,7 @@ mux->bih->biSize=sizeof(BITMAPINFOHEADER);
mux->bih->biPlanes=1;
mux->bih->biBitCount=24;
mux->bih->biCompression=0x6f766976;// 7669766f;
-aviwrite_write_header(avi,f2);
+muxer_write_header(avi,f2);
/*
c=fgetc(f); if(c) printf("error! not vivo file?\n");
@@ -222,7 +222,7 @@ while((c=fgetc(f))>=0){
// end of frame:
printf("Frame size: %d\n",mux->buffer_len);
h263_decode_picture_header(mux->buffer);
- aviwrite_write_chunk(avi,mux,f2,mux->buffer_len,0x10);
+ muxer_write_chunk(avi,mux,f2,mux->buffer_len,0x10);
mux->buffer_len=0;
if((v_id&0xF0)==0x10) fprintf(stderr,"hmm. last video packet %02X\n",v_id);
@@ -258,8 +258,8 @@ mux->bih->biWidth=width;
mux->bih->biHeight=height;
mux->bih->biSizeImage=3*width*height;
-aviwrite_write_index(avi,f2);
+muxer_write_index(avi,f2);
fseek(f2,0,SEEK_SET);
-aviwrite_write_header(avi,f2);
+muxer_write_header(avi,f2);
}
diff --git a/cfg-mencoder.h b/cfg-mencoder.h
index 37660d38a1..51c694999c 100644
--- a/cfg-mencoder.h
+++ b/cfg-mencoder.h
@@ -129,6 +129,16 @@ struct config info_conf[]={
{NULL, NULL, 0, 0, 0, 0, NULL}
};
+struct config of_conf[]={
+ {"avi", &out_file_format, CONF_TYPE_FLAG, 0, 0, MUXER_TYPE_AVI, NULL},
+ {"mpeg", &out_file_format, CONF_TYPE_FLAG, 0, 0, MUXER_TYPE_MPEG, NULL},
+ {"help", "\nAvailable output formats:\n"
+ " avi - Microsoft Audio/Video Interleaved\n"
+ " mpeg - MPEG-1 system stream format\n"
+ "\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
+ {NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
static config_t mencoder_opts[]={
/* name, pointer, type, flags, min, max */
{"include", cfg_include, CONF_TYPE_FUNC_PARAM, CONF_NOSAVE, 0, 0, NULL}, /* this must be the first!!! */
@@ -156,6 +166,9 @@ static config_t mencoder_opts[]={
{"oac", oac_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
{"ovc", ovc_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+ // output file format
+ {"of", of_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+
// override FOURCC in output file
{"ffourcc", &force_fourcc, CONF_TYPE_STRING, 0, 4, 4, NULL},
diff --git a/libmpcodecs/ve_divx4.c b/libmpcodecs/ve_divx4.c
index d18713d461..5ef26068cb 100644
--- a/libmpcodecs/ve_divx4.c
+++ b/libmpcodecs/ve_divx4.c
@@ -13,7 +13,7 @@
#include "demuxer.h"
#include "stheader.h"
-#include "aviwrite.h"
+#include "muxer.h"
#include "img_format.h"
#include "mp_image.h"
@@ -44,7 +44,7 @@
static int pass;
extern char* passtmpfile;
-extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);
+extern void mencoder_write_chunk(muxer_stream_t *s,int len,unsigned int flags);
#include <encore2.h>
@@ -96,7 +96,7 @@ struct config divx4opts_conf[]={
};
struct vf_priv_s {
- aviwrite_stream_t* mux;
+ muxer_stream_t* mux;
ENC_RESULT enc_result;
ENC_FRAME enc_frame;
void* enc_handle;
@@ -289,7 +289,7 @@ static int vf_open(vf_instance_t *vf, char* args){
#endif
vf->priv=malloc(sizeof(struct vf_priv_s));
memset(vf->priv,0,sizeof(struct vf_priv_s));
- vf->priv->mux=(aviwrite_stream_t*)args;
+ vf->priv->mux=(muxer_stream_t*)args;
mux_v->bih=malloc(sizeof(BITMAPINFOHEADER));
mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
diff --git a/libmpcodecs/ve_lavc.c b/libmpcodecs/ve_lavc.c
index 30c22b5ef3..b064a777e5 100644
--- a/libmpcodecs/ve_lavc.c
+++ b/libmpcodecs/ve_lavc.c
@@ -20,14 +20,14 @@
#include "demuxer.h"
#include "stheader.h"
-#include "aviwrite.h"
+#include "muxer.h"
#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
extern char* passtmpfile;
-extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);
+extern void mencoder_write_chunk(muxer_stream_t *s,int len,unsigned int flags);
//===========================================================================//
@@ -175,7 +175,7 @@ struct config lavcopts_conf[]={
#endif
struct vf_priv_s {
- aviwrite_stream_t* mux;
+ muxer_stream_t* mux;
AVCodecContext *context;
AVFrame *pic;
AVCodec *codec;
@@ -531,7 +531,7 @@ static int vf_open(vf_instance_t *vf, char* args){
vf->put_image=put_image;
vf->priv=malloc(sizeof(struct vf_priv_s));
memset(vf->priv,0,sizeof(struct vf_priv_s));
- vf->priv->mux=(aviwrite_stream_t*)args;
+ vf->priv->mux=(muxer_stream_t*)args;
/* XXX: hack: some of the MJPEG decoder DLL's needs exported huffman
table, so we define a zero-table, also lavc mjpeg encoder is putting
diff --git a/libmpcodecs/ve_libdv.c b/libmpcodecs/ve_libdv.c
index 221a0354c7..511c059556 100644
--- a/libmpcodecs/ve_libdv.c
+++ b/libmpcodecs/ve_libdv.c
@@ -15,7 +15,7 @@
#include "demuxer.h"
#include "stheader.h"
-#include "aviwrite.h"
+#include "muxer.h"
#include "img_format.h"
#include "mp_image.h"
@@ -23,7 +23,7 @@
#include <libdv/dv.h>
-extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);
+extern void mencoder_write_chunk(muxer_stream_t *s,int len,unsigned int flags);
#ifndef DV_WIDTH
#define DV_WIDTH 720
@@ -32,7 +32,7 @@ extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags
#endif
struct vf_priv_s {
- aviwrite_stream_t* mux;
+ muxer_stream_t* mux;
dv_encoder_t* enc;
};
@@ -91,7 +91,7 @@ static int vf_open(vf_instance_t *vf, char* args){
vf->put_image=put_image;
vf->priv=malloc(sizeof(struct vf_priv_s));
memset(vf->priv,0,sizeof(struct vf_priv_s));
- vf->priv->mux=(aviwrite_stream_t*)args;
+ vf->priv->mux=(muxer_stream_t*)args;
vf->priv->enc=dv_encoder_new(1,1,1); // FIXME, parse some options!
if(!vf->priv->enc) return 0;
diff --git a/libmpcodecs/ve_qtvideo.c b/libmpcodecs/ve_qtvideo.c
index 4c9c2f0573..e8d292fa79 100644
--- a/libmpcodecs/ve_qtvideo.c
+++ b/libmpcodecs/ve_qtvideo.c
@@ -21,7 +21,7 @@
#include "demuxer.h"
#include "stheader.h"
-#include "aviwrite.h"
+#include "muxer.h"
#include "img_format.h"
#include "mp_image.h"
@@ -86,7 +86,7 @@ static long (*CountComponents)(ComponentDescription* desc);
static OSErr (*GetComponentInfo)(Component prev,ComponentDescription* desc,Handle h1,Handle h2,Handle h3);
-extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);
+extern void mencoder_write_chunk(muxer_stream_t *s,int len,unsigned int flags);
//static int format=mmioFOURCC('S','V','Q','1');
@@ -111,7 +111,7 @@ static ImageSequence seq;
struct vf_priv_s {
- aviwrite_stream_t* mux;
+ muxer_stream_t* mux;
//dv_encoder_t* enc;
};
@@ -279,7 +279,7 @@ static int vf_open(vf_instance_t *vf, char* args){
vf->put_image=put_image;
vf->priv=malloc(sizeof(struct vf_priv_s));
memset(vf->priv,0,sizeof(struct vf_priv_s));
- vf->priv->mux=(aviwrite_stream_t*)args;
+ vf->priv->mux=(muxer_stream_t*)args;
mux_v->bih=malloc(sizeof(BITMAPINFOHEADER)+MAX_IDSIZE);
mux_v->bih->biSize=sizeof(BITMAPINFOHEADER)+MAX_IDSIZE;
diff --git a/libmpcodecs/ve_rawrgb.c b/libmpcodecs/ve_rawrgb.c
index 55e119fdf7..2388db5f28 100644
--- a/libmpcodecs/ve_rawrgb.c
+++ b/libmpcodecs/ve_rawrgb.c
@@ -10,18 +10,18 @@
#include "demuxer.h"
#include "stheader.h"
-#include "aviwrite.h"
+#include "muxer.h"
#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
-extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);
+extern void mencoder_write_chunk(muxer_stream_t *s,int len,unsigned int flags);
//===========================================================================//
struct vf_priv_s {
- aviwrite_stream_t* mux;
+ muxer_stream_t* mux;
};
#define mux_v (vf->priv->mux)
@@ -61,7 +61,7 @@ static int vf_open(vf_instance_t *vf, char* args){
vf->put_image=put_image;
vf->priv=malloc(sizeof(struct vf_priv_s));
memset(vf->priv,0,sizeof(struct vf_priv_s));
- vf->priv->mux=(aviwrite_stream_t*)args;
+ vf->priv->mux=(muxer_stream_t*)args;
mux_v->bih=malloc(sizeof(BITMAPINFOHEADER));
mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
diff --git a/libmpcodecs/ve_vfw.c b/libmpcodecs/ve_vfw.c
index 868fb6a385..c1a86da16e 100644
--- a/libmpcodecs/ve_vfw.c
+++ b/libmpcodecs/ve_vfw.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <inttypes.h>
#include "../config.h"
#ifdef USE_WIN32DLL
@@ -18,13 +19,13 @@
#include "wine/vfw.h"
#include "wine/avifmt.h"
-#include "aviwrite.h"
-
#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
-extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);
+#include "muxer.h"
+
+extern void mencoder_write_chunk(muxer_stream_t *s,int len,unsigned int flags);
//===========================================================================//
@@ -38,7 +39,7 @@ struct config vfwopts_conf[]={
};
struct vf_priv_s {
- aviwrite_stream_t* mux;
+ muxer_stream_t* mux;
BITMAPINFOHEADER* bih;
};
@@ -256,7 +257,7 @@ static int vf_open(vf_instance_t *vf, char* args){
vf->put_image=put_image;
vf->priv=malloc(sizeof(struct vf_priv_s));
memset(vf->priv,0,sizeof(struct vf_priv_s));
- vf->priv->mux=(aviwrite_stream_t*)args;
+ vf->priv->mux=(muxer_stream_t*)args;
vfw_bih=malloc(sizeof(BITMAPINFOHEADER));
vfw_bih->biSize=sizeof(BITMAPINFOHEADER);
diff --git a/libmpcodecs/ve_xvid.c b/libmpcodecs/ve_xvid.c
index 460be88c1c..12f1b64bbc 100644
--- a/libmpcodecs/ve_xvid.c
+++ b/libmpcodecs/ve_xvid.c
@@ -13,7 +13,7 @@
#include "demuxer.h"
#include "stheader.h"
-#include "aviwrite.h"
+#include "muxer.h"
#include "img_format.h"
#include "mp_image.h"
@@ -65,7 +65,7 @@ static int const motion_presets[7] = {
};
extern char* passtmpfile;
-extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);
+extern void mencoder_write_chunk(muxer_stream_t *s,int len,unsigned int flags);
static int xvidenc_pass = 0;
static int xvidenc_quality = 4;
@@ -132,7 +132,7 @@ struct config xvidencopts_conf[] = {
};
struct vf_priv_s {
- aviwrite_stream_t* mux;
+ muxer_stream_t* mux;
XVID_ENC_FRAME enc_frame;
void* enc_handle;
vbr_control_t vbr_state;
@@ -487,7 +487,7 @@ vf_open(vf_instance_t *vf, char* args)
vf->put_image = put_image;
vf->priv = malloc(sizeof(struct vf_priv_s));
memset(vf->priv, 0, sizeof(struct vf_priv_s));
- vf->priv->mux = (aviwrite_stream_t*)args;
+ vf->priv->mux = (muxer_stream_t*)args;
vf->priv->mux->bih = malloc(sizeof(BITMAPINFOHEADER));
vf->priv->mux->bih->biSize = sizeof(BITMAPINFOHEADER);
diff --git a/libmpdemux/Makefile b/libmpdemux/Makefile
index f17407e4fa..a9bfdc617b 100644
--- a/libmpdemux/Makefile
+++ b/libmpdemux/Makefile
@@ -3,7 +3,7 @@ LIBNAME = libmpdemux.a
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
diff --git a/libmpdemux/aviwrite.h b/libmpdemux/aviwrite.h
deleted file mode 100644
index feab55cac0..0000000000
--- a/libmpdemux/aviwrite.h
+++ /dev/null
@@ -1,56 +0,0 @@
-
-#define AVIWRITE_MAX_STREAMS 16
-
-#define AVIWRITE_TYPE_VIDEO 0
-#define AVIWRITE_TYPE_AUDIO 1
-
-typedef struct {
- // muxer data:
- int type; // audio or video
- int id; // stream no
- unsigned int ckid; // chunk id (00dc 01wb etc)
- double timer;
- off_t size;
- // buffering:
- unsigned char *buffer;
- unsigned int buffer_size;
- unsigned int buffer_len;
- // source stream:
- void* source; // sh_audio or sh_video
- int codec; // codec used for encoding. 0 means copy
- // avi stream header:
- AVIStreamHeader h; // Rate/Scale and SampleSize must be filled by caller!
- // stream specific:
- WAVEFORMATEX *wf;
- BITMAPINFOHEADER *bih; // in format
-} aviwrite_stream_t;
-
-typedef struct {
- unsigned int id;
- char *text;
-} aviwrite_info_t;
-
-typedef struct {
- // encoding:
- MainAVIHeader avih;
- unsigned int movi_start;
- unsigned int movi_end;
- unsigned int file_end;
- // index:
- AVIINDEXENTRY *idx;
- int idx_pos;
- int idx_size;
- // streams:
- //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);
-
-
-
diff --git a/libmpdemux/muxer.c b/libmpdemux/muxer.c
new file mode 100644
index 0000000000..877be8ae53
--- /dev/null
+++ b/libmpdemux/muxer.c
@@ -0,0 +1,28 @@
+
+#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;
+}
diff --git a/libmpdemux/muxer.h b/libmpdemux/muxer.h
new file mode 100644
index 0000000000..4410209559
--- /dev/null
+++ b/libmpdemux/muxer.h
@@ -0,0 +1,74 @@
+
+#define MUXER_MAX_STREAMS 16
+
+#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
+ 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
+ // avi stream header:
+ AVIStreamHeader h; // Rate/Scale and SampleSize must be filled by caller!
+ // stream specific:
+ WAVEFORMATEX *wf;
+ BITMAPINFOHEADER *bih; // in format
+ // 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 {
+ uint32_t id;
+ char *text;
+} muxer_info_t;
+
+typedef struct muxer_t{
+ // encoding:
+ MainAVIHeader avih;
+ unsigned int movi_start;
+ unsigned int movi_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;
+ 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 *);
+
diff --git a/libmpdemux/aviwrite.c b/libmpdemux/muxer_avi.c
index e70225c7bd..6aaeb044ff 100644
--- a/libmpdemux/aviwrite.c
+++ b/libmpdemux/muxer_avi.c
@@ -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_copyright;
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 @@ aviwrite_stream_t* aviwrite_new_stream(aviwrite_t *muxer,int type){
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 @@ aviwrite_stream_t* aviwrite_new_stream(aviwrite_t *muxer,int type){
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 @@ if(len>0){
}
}
-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 @@ void aviwrite_write_chunk(aviwrite_t *muxer,aviwrite_stream_t *s, FILE *f,int le
}
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 @@ static void write_avi_list(FILE *f,unsigned int id,int len){
// 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 @@ void aviwrite_write_header(aviwrite_t *muxer,FILE *f){
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 @@ void aviwrite_write_header(aviwrite_t *muxer,FILE *f){
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 @@ void aviwrite_write_header(aviwrite_t *muxer,FILE *f){
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 @@ void aviwrite_write_header(aviwrite_t *muxer,FILE *f){
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 @@ info[i].id=0;
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 @@ void aviwrite_write_index(aviwrite_t *muxer,FILE *f){
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;
+}
diff --git a/libmpdemux/muxer_mpeg.c b/libmpdemux/muxer_mpeg.c
new file mode 100644
index 0000000000..b086d245ce
--- /dev/null
+++ b/libmpdemux/muxer_mpeg.c
@@ -0,0 +1,434 @@
+
+#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
+ {