Index: AUTHORS =================================================================== RCS file: /cvsroot/mplayer/main/AUTHORS,v retrieving revision 1.165 diff -u -r1.165 AUTHORS --- AUTHORS 5 Nov 2005 11:58:24 -0000 1.165 +++ AUTHORS 19 Nov 2005 06:22:26 -0000 @@ -343,6 +343,7 @@ Hickey, Corey * telecine/interlacing HOWTO for the MEncoder documentation * advanced audio usage guide for the MPlayer documentation + * muxer frame buffer for MEncoder Hidvégi, Zoltán (Zoli) * filmdint video filter Index: mencoder.c =================================================================== RCS file: /cvsroot/mplayer/main/mencoder.c,v retrieving revision 1.319 diff -u -r1.319 mencoder.c --- mencoder.c 17 Nov 2005 19:17:53 -0000 1.319 +++ mencoder.c 19 Nov 2005 06:22:27 -0000 @@ -833,8 +833,6 @@ mux_v->bih->biCompression, (char *)&mux_v->bih->biCompression); } -if(muxer->fix_stream_parameters) - muxer_stream_fix_parameters(muxer,mux_v); //if(demuxer->file_format!=DEMUXER_TYPE_AVI) pts_from_bps=0; // it must be 0 for mpeg/asf! // ============= AUDIO =============== @@ -933,14 +931,9 @@ mux_a->h.dwStart=audio_delay_fix*mux_a->h.dwRate/mux_a->h.dwScale; mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_SettingAudioDelay,mux_a->h.dwStart*mux_a->h.dwScale/(float)mux_a->h.dwRate); } -if(muxer->fix_stream_parameters) - muxer_stream_fix_parameters(muxer,mux_a); } // if(sh_audio) -mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_WritingAVIHeader); -if (muxer->cont_write_header) muxer_write_header(muxer); - decoded_frameno=0; signal(SIGINT,exit_sighandler); // Interrupt from keyboard Index: libmpdemux/muxer.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer.c,v retrieving revision 1.10 diff -u -r1.10 muxer.c --- libmpdemux/muxer.c 18 Nov 2005 14:39:19 -0000 1.10 +++ libmpdemux/muxer.c 19 Nov 2005 06:22:27 -0000 @@ -48,3 +48,100 @@ } return muxer; } + +/* buffer frames until we either: + * (a) have at least one frame from each stream + * (b) run out of memory */ +void muxer_write_chunk(muxer_stream_t *s, size_t len, unsigned int flags) { + if (s->muxer->muxbuf_skip_buffer) { + s->muxer->cont_write_chunk(s, len, flags); + } + else { + int num = s->muxer->muxbuf_num++; + muxbuf_t *buf; + + s->muxer->muxbuf = realloc(s->muxer->muxbuf, (num+1) * sizeof(muxbuf_t)); + buf = s->muxer->muxbuf + num; + + /* buffer this frame */ + buf->stream = s; + buf->timer = s->timer; + buf->len = len; + buf->flags = flags; + buf->buffer = malloc(len * sizeof (unsigned char)); + if (!buf->buffer) { + mp_msg(MSGT_MUXER, MSGL_FATAL, "Muxer frame buffer cannot allocate memory!\n"); + return; + } + memcpy(buf->buffer, s->buffer, buf->len); + s->muxbuf_seen = 1; + + /* see if we need to keep buffering */ + s->muxer->muxbuf_skip_buffer = 1; + for (num = 0; s->muxer->streams[num]; ++num) + if (!s->muxer->streams[num]->muxbuf_seen) + s->muxer->muxbuf_skip_buffer = 0; + + /* see if we can flush buffer now */ + if (s->muxer->muxbuf_skip_buffer) { + muxbuf_t *tmp_buf = malloc(sizeof(muxbuf_t)); + if (!tmp_buf) { + mp_msg(MSGT_MUXER, MSGL_FATAL, "Muxer frame buffer cannot allocate memory!\n"); + return; + } + mp_msg(MSGT_MUXER, MSGL_V, "Muxer frame buffer sending %d frame(s) to muxer.\n", + s->muxer->muxbuf_num); + + /* fix parameters for all streams */ + for (num = 0; s->muxer->streams[num]; ++num) { + muxer_stream_t *str = s->muxer->streams[num]; + if(str->muxer->fix_stream_parameters) + muxer_stream_fix_parameters(str->muxer, str); + } + + /* write header */ + mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_WritingAVIHeader); + if (s->muxer->cont_write_header) + muxer_write_header(s->muxer); + + /* send all buffered frames to muxer */ + for (num = 0; num < s->muxer->muxbuf_num; ++num) { + buf = s->muxer->muxbuf + num; + s = buf->stream; + + /* 1. save timer and buffer (might have changed by now) */ + tmp_buf->timer = s->timer; + tmp_buf->buffer = s->buffer; + + /* 2. move stored timer and buffer into stream and mux it */ + s->timer = buf->timer; + s->buffer = buf->buffer; + s->muxer->cont_write_chunk(s, buf->len, buf->flags); + + /* 3. restore saved timer and buffer */ + s->timer = tmp_buf->timer; + s->buffer = tmp_buf->buffer; + } + free(tmp_buf); + + free(s->muxer->muxbuf); + s->muxer->muxbuf_num = 0; + } + } + + /* this code moved directly from muxer_avi.c */ + // alter counters: + if(s->h.dwSampleSize){ + // CBR + s->h.dwLength+=len/s->h.dwSampleSize; + if(len%s->h.dwSampleSize) mp_msg(MSGT_MUXER, MSGL_WARN, "Warning! len isn't divisable by samplesize!\n"); + } else { + // VBR + s->h.dwLength++; + } + s->timer=(double)s->h.dwLength*s->h.dwScale/s->h.dwRate; + s->size+=len; + + return; +} + Index: libmpdemux/muxer.h =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer.h,v retrieving revision 1.15 diff -u -r1.15 muxer.h --- libmpdemux/muxer.h 19 Jun 2005 09:12:43 -0000 1.15 +++ libmpdemux/muxer.h 19 Nov 2005 06:22:27 -0000 @@ -28,6 +28,8 @@ 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 + // muxer frame buffer: + unsigned int muxbuf_seen; // source stream: void* source; // sh_audio or sh_video int codec; // codec used for encoding. 0 means copy @@ -37,7 +39,6 @@ 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 of that stream struct muxer_t *muxer; @@ -66,6 +67,11 @@ //int num_streams; muxer_stream_t* def_v; // default video stream (for general headers) muxer_stream_t* streams[MUXER_MAX_STREAMS]; + // muxer frame buffer: + struct muxbuf_t * muxbuf; + int muxbuf_num; + int muxbuf_skip_buffer; + // functions: 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 *); @@ -75,10 +81,20 @@ void *priv; } muxer_t; +/* muxer frame buffer */ +typedef struct muxbuf_t { + muxer_stream_t *stream; /* pointer back to corresponding stream */ + double timer; /* snapshot of stream timer */ + unsigned char *buffer; + size_t len; + unsigned int flags; +} muxbuf_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) +void muxer_write_chunk(muxer_stream_t *s, size_t len, unsigned int flags); #define muxer_write_header(muxer) muxer->cont_write_header(muxer) #define muxer_write_index(muxer) muxer->cont_write_index(muxer) Index: libmpdemux/muxer_avi.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_avi.c,v retrieving revision 1.31 diff -u -r1.31 muxer_avi.c --- libmpdemux/muxer_avi.c 18 Nov 2005 14:39:19 -0000 1.31 +++ libmpdemux/muxer_avi.c 19 Nov 2005 06:22:27 -0000 @@ -241,20 +241,9 @@ // write out the chunk: write_avi_chunk(muxer->file,s->ckid,len,s->buffer); /* unsigned char */ - // alter counters: if (len > s->h.dwSuggestedBufferSize){ s->h.dwSuggestedBufferSize = len; } - if(s->h.dwSampleSize){ - // CBR - s->h.dwLength+=len/s->h.dwSampleSize; - if(len%s->h.dwSampleSize) mp_msg(MSGT_MUXER, MSGL_WARN, "Warning! len isn't divisable by samplesize!\n"); - } else { - // VBR - s->h.dwLength++; - } - s->timer=(double)s->h.dwLength*s->h.dwScale/s->h.dwRate; - s->size+=len; if((unsigned int)len>s->h.dwSuggestedBufferSize) s->h.dwSuggestedBufferSize=len; muxer->file_end += 8 + paddedlen; Index: libmpdemux/muxer_lavf.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_lavf.c,v retrieving revision 1.12 diff -u -r1.12 muxer_lavf.c --- libmpdemux/muxer_lavf.c 18 Nov 2005 14:39:19 -0000 1.12 +++ libmpdemux/muxer_lavf.c 19 Nov 2005 06:22:27 -0000 @@ -103,6 +103,7 @@ mp_msg(MSGT_MUXER, MSGL_ERR, "Could not alloc muxer_stream, EXIT\n"); return NULL; } + muxer->streams[muxer->avih.dwStreams] = stream; stream->b_buffer = (unsigned char *)malloc(2048); if(!stream->b_buffer) { @@ -259,12 +260,6 @@ } } - if(stream->h.dwSampleSize) // CBR - stream->h.dwLength += len / stream->h.dwSampleSize; - else // VBR - stream->h.dwLength++; - - stream->timer = (double) stream->h.dwLength * stream->h.dwScale / stream->h.dwRate; return; } Index: libmpdemux/muxer_mpeg.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_mpeg.c,v retrieving revision 1.22 diff -u -r1.22 muxer_mpeg.c --- libmpdemux/muxer_mpeg.c 18 Nov 2005 14:39:19 -0000 1.22 +++ libmpdemux/muxer_mpeg.c 19 Nov 2005 06:22:27 -0000 @@ -1991,7 +1991,6 @@ 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++; @@ -2296,7 +2295,7 @@ extern int aac_parse_frame(uint8_t *buf, int *srate, int *num); -static int parse_audio(muxer_stream_t *s, int finalize, int *nf, double *timer) +static int parse_audio(muxer_stream_t *s, int finalize) { int i, len, chans, srate, spf, layer, dummy, tot, num, frames; uint64_t idur; @@ -2391,8 +2390,6 @@ if(finalize) add_audio_frame(spriv, 0, s->b_buffer, s->b_buffer_len); - *nf = frames; - *timer = (double) (spriv->last_pts - spriv->init_pts)/92160000.0; return tot; } @@ -2407,7 +2404,7 @@ muxer_headers_t *spriv = (muxer_headers_t*) s->priv; FILE *f; float fps; - uint32_t stream_format, nf; + uint32_t stream_format; f = muxer->file; @@ -2454,9 +2451,6 @@ priv->vbytes += len; sz <<= 1; - s->h.dwLength++; - s->size += len; - s->timer = (double)s->h.dwLength*s->h.dwScale/s->h.dwRate; } else { // MUXER_TYPE_AUDIO spriv->type = 0; stream_format = s->wf->wFormatTag; @@ -2522,9 +2516,7 @@ } } - parse_audio(s, 0, &nf, &(s->timer)); - s->h.dwLength += nf; - s->size += len; + parse_audio(s, 0); sz = max(len, 2 * priv->packet_size); } @@ -2556,13 +2548,13 @@ static void mpegfile_write_index(muxer_t *muxer) { - int i, nf; + int i; muxer_priv_t *priv = (muxer_priv_t *) muxer->priv; for(i = 0; i < muxer->avih.dwStreams; i++) { if(muxer->streams[i]->type == MUXER_TYPE_AUDIO) - parse_audio(muxer->streams[i], 1, &nf, &(muxer->streams[i]->timer)); + parse_audio(muxer->streams[i], 1); } while(flush_buffers(muxer, 0) > 0); flush_buffers(muxer, 1); Index: libmpdemux/muxer_rawaudio.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_rawaudio.c,v retrieving revision 1.2 diff -u -r1.2 muxer_rawaudio.c --- libmpdemux/muxer_rawaudio.c 20 Jun 2005 00:30:18 -0000 1.2 +++ libmpdemux/muxer_rawaudio.c 19 Nov 2005 06:22:27 -0000 @@ -51,19 +51,6 @@ // write out the chunk: if (s->type==MUXER_TYPE_AUDIO) fwrite(s->buffer,len,1,muxer->file); - - // alter counters: - if(s->h.dwSampleSize){ - // CBR - s->h.dwLength+=len/s->h.dwSampleSize; - if(len%s->h.dwSampleSize) - mp_msg(MSGT_MUXER,MSGL_WARN,MSGTR_WarningLenIsntDivisible); - } else { - // VBR - s->h.dwLength++; - } - s->timer=(double)s->h.dwLength*s->h.dwScale/s->h.dwRate; - s->size+=len; } static void rawaudiofile_write_header(muxer_t *muxer){ Index: libmpdemux/muxer_rawvideo.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_rawvideo.c,v retrieving revision 1.5 diff -u -r1.5 muxer_rawvideo.c --- libmpdemux/muxer_rawvideo.c 18 Nov 2005 14:39:19 -0000 1.5 +++ libmpdemux/muxer_rawvideo.c 19 Nov 2005 06:22:27 -0000 @@ -57,17 +57,6 @@ if (s->type == MUXER_TYPE_VIDEO) write_rawvideo_chunk(muxer->file,len,s->buffer); /* unsigned char */ - // 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++; - } - s->timer=(double)s->h.dwLength*s->h.dwScale/s->h.dwRate; - s->size+=len; // if((unsigned int)len>s->h.dwSuggestedBufferSize) s->h.dwSuggestedBufferSize=len; }