2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "aviheader.h"
29 #include "stream/stream.h"
36 muxer_t
*muxer_new_muxer(int type
,stream_t
*stream
){
37 muxer_t
* muxer
=calloc(1,sizeof(muxer_t
));
40 muxer
->stream
= stream
;
43 if(! muxer_init_muxer_mpeg(muxer
))
46 case MUXER_TYPE_RAWVIDEO
:
47 if(! muxer_init_muxer_rawvideo(muxer
))
50 case MUXER_TYPE_RAWAUDIO
:
51 if(! muxer_init_muxer_rawaudio(muxer
))
54 #ifdef CONFIG_LIBAVFORMAT
56 if(! muxer_init_muxer_lavf(muxer
))
62 if(! muxer_init_muxer_avi(muxer
))
72 /* buffer frames until we either:
73 * (a) have at least one frame from each stream
74 * (b) run out of memory */
75 void muxer_write_chunk(muxer_stream_t
*s
, size_t len
, unsigned int flags
, double dts
, double pts
) {
76 if(dts
== MP_NOPTS_VALUE
) dts
= s
->timer
;
77 if(pts
== MP_NOPTS_VALUE
) pts
= s
->timer
; // this is wrong
79 if (s
->muxer
->muxbuf_skip_buffer
) {
80 s
->muxer
->cont_write_chunk(s
, len
, flags
, dts
, pts
);
83 int num
= s
->muxer
->muxbuf_num
++;
86 tmp
= realloc_struct(s
->muxer
->muxbuf
, (num
+1), sizeof(muxbuf_t
));
88 mp_msg(MSGT_MUXER
, MSGL_FATAL
, MSGTR_MuxbufReallocErr
);
91 s
->muxer
->muxbuf
= tmp
;
92 buf
= s
->muxer
->muxbuf
+ num
;
94 /* buffer this frame */
100 buf
->buffer
= malloc(len
);
102 mp_msg(MSGT_MUXER
, MSGL_FATAL
, MSGTR_MuxbufMallocErr
);
105 memcpy(buf
->buffer
, s
->buffer
, buf
->len
);
108 /* see if we need to keep buffering */
109 s
->muxer
->muxbuf_skip_buffer
= 1;
110 for (num
= 0; s
->muxer
->streams
[num
]; ++num
)
111 if (!s
->muxer
->streams
[num
]->muxbuf_seen
)
112 s
->muxer
->muxbuf_skip_buffer
= 0;
114 /* see if we can flush buffer now */
115 if (s
->muxer
->muxbuf_skip_buffer
) {
116 mp_msg(MSGT_MUXER
, MSGL_V
, MSGTR_MuxbufSending
, s
->muxer
->muxbuf_num
);
118 /* fix parameters for all streams */
119 for (num
= 0; s
->muxer
->streams
[num
]; ++num
) {
120 muxer_stream_t
*str
= s
->muxer
->streams
[num
];
121 if(str
->muxer
->fix_stream_parameters
)
122 muxer_stream_fix_parameters(str
->muxer
, str
);
126 if (s
->muxer
->cont_write_header
)
127 muxer_write_header(s
->muxer
);
129 /* send all buffered frames to muxer */
130 for (num
= 0; num
< s
->muxer
->muxbuf_num
; ++num
) {
132 buf
= s
->muxer
->muxbuf
+ num
;
135 /* 1. save timer and buffer (might have changed by now) */
136 tmp_buf
.dts
= s
->timer
;
137 tmp_buf
.buffer
= s
->buffer
;
139 /* 2. move stored timer and buffer into stream and mux it */
141 s
->buffer
= buf
->buffer
;
142 s
->muxer
->cont_write_chunk(s
, buf
->len
, buf
->flags
, buf
->dts
, buf
->pts
);
144 /* 3. restore saved timer and buffer */
145 s
->timer
= tmp_buf
.dts
;
146 s
->buffer
= tmp_buf
.buffer
;
149 free(s
->muxer
->muxbuf
);
150 s
->muxer
->muxbuf_num
= 0;
154 /* this code moved directly from muxer_avi.c */
156 if(s
->h
.dwSampleSize
){
158 s
->h
.dwLength
+=len
/s
->h
.dwSampleSize
;
159 if(len
%s
->h
.dwSampleSize
) mp_msg(MSGT_MUXER
, MSGL_WARN
, MSGTR_WarningLenIsntDivisible
);
164 s
->timer
=(double)s
->h
.dwLength
*s
->h
.dwScale
/s
->h
.dwRate
;