Index: mencoder.c =================================================================== RCS file: /cvsroot/mplayer/main/mencoder.c,v retrieving revision 1.318 diff -u -r1.318 mencoder.c --- mencoder.c 30 Oct 2005 09:11:40 -0000 1.318 +++ mencoder.c 13 Nov 2005 21:05:36 -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 =============== @@ -938,9 +936,6 @@ } // 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.9 diff -u -r1.9 muxer.c --- libmpdemux/muxer.c 21 Jun 2005 18:54:50 -0000 1.9 +++ libmpdemux/muxer.c 13 Nov 2005 21:05:37 -0000 @@ -48,3 +48,93 @@ } return muxer; } + +/* buffer frames until we either: + * (a) have a video stream + * (b) give up because we think there is no video coming */ +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++; + + /* buffer this frame */ + s->muxer->muxbuf_stream[num] = s; + s->muxer->muxbuf_timer[num] = s->timer; + s->muxer->muxbuf_buffer_len[num] = len > s->buffer_len ? len : s->buffer_len; + s->muxer->muxbuf_len[num] = len; + s->muxer->muxbuf_flags[num] = flags; + s->muxer->muxbuf_buffer[num] = malloc(s->muxer->muxbuf_buffer_len[num]); + if (!s->muxer->muxbuf_buffer[num]) { + /* TODO: do something reasonable here */ + mp_msg(MSGT_MUXER, MSGL_FATAL, "Muxer frame buffer cannot allocate memory!\n"); + } + memcpy(s->muxer->muxbuf_buffer[num], s->buffer, s->muxer->muxbuf_buffer_len[num]); + + /* see if we have a video frame or if buffer is full */ + if (s->type == MUXER_TYPE_VIDEO || s->muxer->muxbuf_num >= MUXER_FRAME_BUFFER_SIZE) { + unsigned char *tmp_buffer; + double tmp_timer; + + if (s->muxer->muxbuf_num >= MUXER_FRAME_BUFFER_SIZE) /* buffer full */ + mp_msg(MSGT_MUXER, MSGL_ERR, "Muxer frame buffer has %d non-video frames.\n" + "Sending all frames to muxer anyway -- header may be incorrect.\n", + s->muxer->muxbuf_num); + else { /* this is a video frame */ + mp_msg(MSGT_MUXER, MSGL_V, "Muxer frame buffer sending %d frame(s) to muxer.\n", + s->muxer->muxbuf_num); + if(s->muxer->fix_stream_parameters) + muxer_stream_fix_parameters(s->muxer, s); + } + + /* 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) { + s = s->muxer->muxbuf_stream[num]; + + /* 1. save current timer and buffer (might have changed by now) */ + tmp_timer = s->timer; + tmp_buffer = malloc(s->muxer->muxbuf_buffer_len[num]); + if (!tmp_buffer) { + /* TODO: do something reasonable here */ + mp_msg(MSGT_MUXER, MSGL_FATAL, "Muxer frame buffer cannot allocate memory!\n"); + } + memcpy(tmp_buffer, s->buffer, s->muxer->muxbuf_buffer_len[num]); + + /* 2. move stored timer and buffer into stream and mux it */ + s->timer = s->muxer->muxbuf_timer[num]; + memcpy(s->buffer, s->muxer->muxbuf_buffer[num], s->muxer->muxbuf_buffer_len[num]); + free(s->muxer->muxbuf_buffer[num]); + s->muxer->cont_write_chunk(s, s->muxer->muxbuf_len[num], s->muxer->muxbuf_flags[num]); + + /* 3. put temporarily saved timer and buffer back into stream */ + s->timer = tmp_timer; + memcpy(s->buffer, tmp_buffer, s->muxer->muxbuf_buffer_len[num]); + free(tmp_buffer); + } + + s->muxer->muxbuf_num = 0; + s->muxer->muxbuf_skip_buffer = 1; + } + } + + /* 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 13 Nov 2005 21:05:37 -0000 @@ -1,5 +1,6 @@ #define MUXER_MAX_STREAMS 16 +#define MUXER_FRAME_BUFFER_SIZE 100 // arbitrary number. what would be good? #define MUXER_TYPE_VIDEO 0 #define MUXER_TYPE_AUDIO 1 @@ -37,7 +38,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 +66,16 @@ //int num_streams; muxer_stream_t* def_v; // default video stream (for general headers) muxer_stream_t* streams[MUXER_MAX_STREAMS]; + // for prebuffering frames until we get a video frame + muxer_stream_t *muxbuf_stream[MUXER_FRAME_BUFFER_SIZE]; // corresponding stream + double muxbuf_timer[MUXER_FRAME_BUFFER_SIZE]; // snapshot of stream timer + unsigned int muxbuf_buffer_len[MUXER_FRAME_BUFFER_SIZE]; // used length of buffer + size_t muxbuf_len[MUXER_FRAME_BUFFER_SIZE]; // amount of buffer to be muxed + unsigned int muxbuf_flags[MUXER_FRAME_BUFFER_SIZE]; + unsigned char *muxbuf_buffer[MUXER_FRAME_BUFFER_SIZE]; + 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 *); @@ -78,7 +88,7 @@ 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.30 diff -u -r1.30 muxer_avi.c --- libmpdemux/muxer_avi.c 21 Feb 2005 21:45:49 -0000 1.30 +++ libmpdemux/muxer_avi.c 13 Nov 2005 21:05:37 -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.11 diff -u -r1.11 muxer_lavf.c --- libmpdemux/muxer_lavf.c 13 Oct 2005 18:33:56 -0000 1.11 +++ libmpdemux/muxer_lavf.c 13 Nov 2005 21:05:37 -0000 @@ -259,12 +259,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.21 diff -u -r1.21 muxer_mpeg.c --- libmpdemux/muxer_mpeg.c 13 Oct 2005 18:33:56 -0000 1.21 +++ libmpdemux/muxer_mpeg.c 13 Nov 2005 21:05:37 -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 13 Nov 2005 21:05:37 -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.4 diff -u -r1.4 muxer_rawvideo.c --- libmpdemux/muxer_rawvideo.c 19 Oct 2005 05:44:27 -0000 1.4 +++ libmpdemux/muxer_rawvideo.c 13 Nov 2005 21:05:37 -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; }