Mercurial > mplayer.hg
changeset 17023:dd5be8f8d16d
buffering in the muxer layer; patch by Corey Hickey (bugfood-ml ad fatooh punctum org) plus small fixes by me
author | nicodvb |
---|---|
date | Mon, 21 Nov 2005 22:53:14 +0000 |
parents | 2627a9e6570c |
children | c20b4b1d0676 |
files | AUTHORS libmpdemux/muxer.c libmpdemux/muxer.h libmpdemux/muxer_avi.c libmpdemux/muxer_lavf.c libmpdemux/muxer_mpeg.c libmpdemux/muxer_rawaudio.c libmpdemux/muxer_rawvideo.c mencoder.c |
diffstat | 9 files changed, 126 insertions(+), 60 deletions(-) [+] |
line wrap: on
line diff
--- a/AUTHORS Mon Nov 21 21:17:27 2005 +0000 +++ b/AUTHORS Mon Nov 21 22:53:14 2005 +0000 @@ -343,6 +343,7 @@ Hickey, Corey <bugfood-ml@fatooh.org> * 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) <mplayer@hzoli.com> * filmdint video filter
--- a/libmpdemux/muxer.c Mon Nov 21 21:17:27 2005 +0000 +++ b/libmpdemux/muxer.c Mon Nov 21 22:53:14 2005 +0000 @@ -48,3 +48,105 @@ } 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, *tmp; + + tmp = realloc(s->muxer->muxbuf, (num+1) * sizeof(muxbuf_t)); + if(!tmp) { + mp_msg(MSGT_MUXER, MSGL_FATAL, "Muxer frame buffer cannot reallocate memory!\n"); + return; + } + s->muxer->muxbuf = tmp; + 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; +} +
--- a/libmpdemux/muxer.h Mon Nov 21 21:17:27 2005 +0000 +++ b/libmpdemux/muxer.h Mon Nov 21 22:53:14 2005 +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)
--- a/libmpdemux/muxer_avi.c Mon Nov 21 21:17:27 2005 +0000 +++ b/libmpdemux/muxer_avi.c Mon Nov 21 22:53:14 2005 +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;
--- a/libmpdemux/muxer_lavf.c Mon Nov 21 21:17:27 2005 +0000 +++ b/libmpdemux/muxer_lavf.c Mon Nov 21 22:53:14 2005 +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) { @@ -230,8 +231,6 @@ muxer_stream_priv_t *spriv = (muxer_stream_priv_t *) stream->priv; AVPacket pkt; - stream->size += len; - if(len) { av_init_packet(&pkt); @@ -259,12 +258,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; }
--- a/libmpdemux/muxer_mpeg.c Mon Nov 21 21:17:27 2005 +0000 +++ b/libmpdemux/muxer_mpeg.c Mon Nov 21 22:53:14 2005 +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++; @@ -2454,10 +2453,8 @@ 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 + double fake_timer; spriv->type = 0; stream_format = s->wf->wFormatTag; @@ -2522,9 +2519,7 @@ } } - parse_audio(s, 0, &nf, &(s->timer)); - s->h.dwLength += nf; - s->size += len; + parse_audio(s, 0, &nf, &fake_timer); sz = max(len, 2 * priv->packet_size); } @@ -2557,12 +2552,13 @@ static void mpegfile_write_index(muxer_t *muxer) { int i, nf; + double fake_timer; 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, &nf, &fake_timer); } while(flush_buffers(muxer, 0) > 0); flush_buffers(muxer, 1);
--- a/libmpdemux/muxer_rawaudio.c Mon Nov 21 21:17:27 2005 +0000 +++ b/libmpdemux/muxer_rawaudio.c Mon Nov 21 22:53:14 2005 +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){
--- a/libmpdemux/muxer_rawvideo.c Mon Nov 21 21:17:27 2005 +0000 +++ b/libmpdemux/muxer_rawvideo.c Mon Nov 21 22:53:14 2005 +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; }
--- a/mencoder.c Mon Nov 21 21:17:27 2005 +0000 +++ b/mencoder.c Mon Nov 21 22:53:14 2005 +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