8 #include "../version.h"
11 #include "wine/mmreg.h"
12 #include "wine/avifmt.h"
18 // 18 bytes reserved for block headers and STD
19 #define MUXER_MPEG_DATASIZE (MUXER_MPEG_BLOCKSIZE-18)
21 // ISO-11172 requirements
22 #define MPEG_MAX_PTS_DELAY 90000 /* 1s */
23 #define MPEG_MAX_SCR_INTERVAL 63000 /* 0.7s */
26 #define MPEG_STARTPTS 45000 /* 0.5s */
27 #define MPEG_MIN_PTS_DELAY 9000 /* 0.1s */
28 #define MPEG_STARTSCR 9 /* 0.1ms */
30 //static unsigned int mpeg_min_delay;
31 //static unsigned int mpeg_max_delay;
33 static muxer_stream_t
* mpegfile_new_stream(muxer_t
*muxer
,int type
){
36 if (!muxer
) return NULL
;
37 if(muxer
->avih
.dwStreams
>=MUXER_MAX_STREAMS
){
38 printf("Too many streams! increase MUXER_MAX_STREAMS !\n");
42 case MUXER_TYPE_VIDEO
:
43 if (muxer
->num_videos
>= 15) {
44 printf ("MPEG stream can't contain above of 15 video streams!\n");
48 case MUXER_TYPE_AUDIO
:
49 if (muxer
->avih
.dwStreams
- muxer
->num_videos
>= 31) {
50 printf ("MPEG stream can't contain above of 31 audio streams!\n");
55 printf ("Unknown stream type!\n");
58 s
=malloc(sizeof(muxer_stream_t
));
59 memset(s
,0,sizeof(muxer_stream_t
));
60 if(!s
) return NULL
; // no mem!?
61 if (!(s
->b_buffer
= malloc (MUXER_MPEG_BLOCKSIZE
))) {
63 return NULL
; // no mem?!
65 muxer
->streams
[muxer
->avih
.dwStreams
]=s
;
67 s
->id
=muxer
->avih
.dwStreams
;
71 if (type
== MUXER_TYPE_VIDEO
) {
72 s
->ckid
= be2me_32 (0x1e0 + muxer
->num_videos
);
74 s
->h
.fccType
=streamtypeVIDEO
;
75 if(!muxer
->def_v
) muxer
->def_v
=s
;
76 mp_msg (MSGT_MUXER
, MSGL_DBG2
, "Added video stream %d, ckid=%X\n", muxer
->num_videos
, s
->ckid
);
77 } else { // MUXER_TYPE_AUDIO
78 s
->ckid
= be2me_32 (0x1c0 + s
->id
- muxer
->num_videos
);
79 s
->h
.fccType
=streamtypeAUDIO
;
80 mp_msg (MSGT_MUXER
, MSGL_DBG2
, "Added audio stream %d, ckid=%X\n", s
->id
- muxer
->num_videos
+ 1, s
->ckid
);
82 muxer
->avih
.dwStreams
++;
86 static void write_mpeg_ts(unsigned char *b
, unsigned int ts
, char mod
) {
87 b
[0] = ((ts
>> 29) & 0xf) | 1 | mod
;
88 b
[1] = (ts
>> 22) & 0xff;
89 b
[2] = ((ts
>> 14) & 0xff) | 1;
90 b
[3] = (ts
>> 7) & 0xff;
91 b
[4] = ((ts
<< 1) & 0xff) | 1;
94 static void write_mpeg_rate(unsigned char *b
, unsigned int rate
) {
96 rate
--; // for round upward
98 rate
++; // round upward
99 b
[0] = ((rate
>> 15) & 0x7f) | 0x80;
100 b
[1] = (rate
>> 7) & 0xff;
101 b
[2] = ((rate
<< 1) & 0xff) | 1;
104 static void write_mpeg_std(unsigned char *b
, unsigned int size
, char mod
) {
106 size
--; // for round upward
107 if (size
< (128 << 8))
108 size
>>= 7; // by 128 bytes
111 size
|= 0x2000; // by 1kbyte
113 size
++; // round upward
114 b
[0] = ((size
>> 8) & 0x3f) | 0x40 | mod
;
118 static int write_mpeg_block(muxer_t
*muxer
, muxer_stream_t
*s
, FILE *f
, char *bl
, size_t len
, int isoend
){
119 size_t sz
; // rest in block buffer
120 unsigned char buff
[12]; // 0x1ba header
121 unsigned int mints
=0;
124 mp_dbg(MSGT_MUXER
, MSGL_DBG3
, " MPEG block: size=%u, scr=%u, rate=%u, id=%X;", len
, muxer
->file_end
, muxer
->sysrate
, s
->ckid
);
125 if (s
->b_buffer_ptr
== 0) { // 00001111 if no PTS
126 s
->b_buffer
[0] = 0xf;
128 sz
= MUXER_MPEG_DATASIZE
-1;
129 } else if (s
->b_buffer_ptr
> MUXER_MPEG_DATASIZE
) {
130 printf ("Unknown error in write_mpeg_block()!\n");
133 sz
= MUXER_MPEG_DATASIZE
- s
->b_buffer_ptr
;
134 if (s
->b_buffer
[7] == 0xff) // PTS not set yet
135 s
->b_buffer
[11] = 0xf; // terminate stuFFing bytes
139 *(uint32_t *)buff
= be2me_32 (0x1ba);
140 write_mpeg_ts (buff
+4, muxer
->file_end
, 0x20); // 0010 and SCR
141 write_mpeg_rate (buff
+9, muxer
->sysrate
);
142 fwrite (buff
, 12, 1, f
);
143 fwrite (&s
->ckid
, 4, 1, f
); // stream_id
144 memset (buff
, 0xff, 12); // stuFFing bytes
146 // calculate padding bytes in buffer
147 while (mints
< s
->b_buffer_ptr
&& s
->b_buffer
[mints
] == 0xff) mints
++;
148 if (mints
+sz
< 12) { // cannot write padding block so write up to 12 stuFFing bytes
149 l1
= be2me_16 (MUXER_MPEG_DATASIZE
);
150 fwrite (&l1
, 2, 1, f
);
151 mints
= 0; // so stuFFed bytes will be written all
153 fwrite (buff
, sz
, 1, f
);
154 sz
= 0; // no padding block anyway
155 } else { // use padding block
156 if (sz
> 6) // sufficient for PAD header so don't shorter data
159 sz
+= mints
; // skip stuFFing bytes (sz>8 here)
160 l1
= be2me_16 (s
->b_buffer_ptr
+len
-mints
);
161 fwrite (&l1
, 2, 1, f
);
164 fwrite (s
->b_buffer
+mints
, s
->b_buffer_ptr
-mints
, 1, f
);
166 fwrite (bl
, len
, 1, f
);
167 if (sz
> 6) { // padding block (0x1be)
171 l0
= be2me_32 (0x1b9);
173 l0
= be2me_32 (0x1be);
176 fwrite (&l0
, 4, 1, f
);
177 fwrite (&l1
, 2, 1, f
);
178 memset (s
->b_buffer
, 0xff, sz
); // stuFFing bytes
179 fwrite (s
->b_buffer
, sz
, 1, f
);
182 muxer
->movi_end
+= MUXER_MPEG_BLOCKSIZE
;
183 // prepare timestamps for next pack
184 mints
= (MUXER_MPEG_BLOCKSIZE
*90000/muxer
->sysrate
)+1; // min ts delta
185 sz
= (int)(s
->timer
*90000) + MPEG_STARTPTS
; // new PTS
186 if (sz
> muxer
->file_end
)
187 sz
-= muxer
->file_end
; // suggested ts delta
191 printf ("Error in stream: PTS earlier than SCR!\n");
193 if (sz
> MPEG_MAX_PTS_DELAY
) {
194 // printf ("Warning: attempt to set PTS to SCR delay to %u \n", sz);
195 mints
= sz
-MPEG_MAX_PTS_DELAY
; // try to compensate
196 if (mints
> MPEG_MAX_SCR_INTERVAL
) {
197 printf ("Error in stream: SCR interval %u is too big!\n", mints
);
199 } else if (sz
> 54000) // assume 0.3...0.7s is optimal
200 mints
+= (sz
-45000)>>2; // reach 0.5s in 4 blocks ?
201 else if (sz
< 27000) {
202 unsigned int newsysrate
= 0;
204 if (s
->timer
> 0.5) // too early to calculate???
205 newsysrate
= muxer
->movi_end
/(s
->timer
*0.4); // pike-factor 2.5 (8dB)
206 if (sz
< MPEG_MIN_PTS_DELAY
)
207 printf ("Error in stream: PTS to SCR delay %u is too little!\n", sz
);
208 if (muxer
->sysrate
< newsysrate
)
209 muxer
->sysrate
= newsysrate
; // increase next rate to current rate
210 else if (!newsysrate
)
211 muxer
->sysrate
+= muxer
->sysrate
>>3; // increase next rate by 25%
213 muxer
->file_end
+= mints
; // update the system timestamp
217 static void set_mpeg_pts(muxer_t
*muxer
, muxer_stream_t
*s
, unsigned int pts
) {
218 unsigned int dts
, nts
;
220 if (s
->b_buffer_ptr
!= 0 && s
->b_buffer
[7] != 0xff)
221 return; // already set
222 if (s
->b_buffer_ptr
== 0) {
223 memset (s
->b_buffer
, 0xff, 7); // reserved for PTS or STD, stuFFing for now
224 s
->b_buffer_ptr
= 12;
226 dts
= (int)(s
->timer
*90000) + MPEG_STARTPTS
; // PTS
228 write_mpeg_ts (s
->b_buffer
+2, pts
, 0x30); // 0011 and both PTS/DTS
230 write_mpeg_ts (s
->b_buffer
+7, dts
, 0x20); // 0010 and PTS only
233 nts
= dts
- muxer
->file_end
;
234 // if (nts < mpeg_min_delay) mpeg_min_delay = nts;
235 // if (nts > mpeg_max_delay) mpeg_max_delay = nts;
236 nts
= 180000*s
->h
.dwScale
/s
->h
.dwRate
; // two frames
237 if (dts
-nts
< muxer
->file_end
) {
238 dts
+= muxer
->file_end
;
239 dts
/= 2; // calculate average time
240 printf ("Warning: DTS to SCR delay is too small\n");
243 dts
-= nts
/2; // one frame :)
244 mp_dbg(MSGT_MUXER
, MSGL_DBG3
, ", dts=%u", dts
);
245 write_mpeg_ts (s
->b_buffer
+7, dts
, 0x10);
248 static void mpegfile_write_chunk(muxer_stream_t
*s
,size_t len
,unsigned int flags
){
251 muxer_t
*muxer
= s
->muxer
;
255 if (s
->type
== MUXER_TYPE_VIDEO
) { // try to recognize frame type...
256 if (s
->buffer
[0] != 0 || s
->buffer
[1] != 0 || s
->buffer
[2] != 1 || len
<6) {
257 printf ("Unknown block type, possibly non-MPEG stream!\n");
260 } else if (s
->buffer
[3] == 0 || s
->buffer
[3] == 0xb3 ||
261 s
->buffer
[3] == 0xb8) { // Picture or GOP
265 if (s
->buffer
[3]) { // GOP -- scan for Picture
266 s
->gop_start
= s
->h
.dwLength
;
267 while (ptr
< len
-5 && (s
->buffer
[ptr
] != 0 || s
->buffer
[ptr
+1] != 0 ||
268 s
->buffer
[ptr
+2] != 1 || s
->buffer
[ptr
+3] != 0)) ptr
++;
269 if (s
->b_buffer_ptr
> MUXER_MPEG_DATASIZE
-39-12) { // 39 bytes for Gop+Pic+Slice headers
270 write_mpeg_block (muxer
, s
, f
, NULL
, 0, 0);
274 pt
= 0; // Picture not found?!
276 printf ("Warning: picture not found in GOP!\n");
278 pt
= (s
->buffer
[ptr
+5]>>3) & 7;
279 temp_ref
= (s
->buffer
[ptr
+4]<<2)+(s
->buffer
[ptr
+5]>>6);
282 temp_ref
+= s
->gop_start
;
284 case 2: // predictive
286 sz
= len
+ s
->ipb
[0];
287 if (s
->ipb
[0] < s
->ipb
[2])
288 s
->ipb
[0] = s
->ipb
[2];
290 } else if (s
->ipb
[2]) {
291 sz
= len
+ s
->ipb
[2];
292 s
->ipb
[0] = s
->ipb
[2];
295 sz
= 4 * len
; // no bidirectional frames yet?
297 // pictires may be not in frame sequence so recalculate timer
298 pts
= (int)(90000*((double)temp_ref
*s
->h
.dwScale
/s
->h
.dwRate
)) + MPEG_STARTPTS
;
300 case 3: // bidirectional
302 sz
= s
->ipb
[1] + s
->ipb
[2];
303 // pictires may be not in frame sequence so recalculate timer
304 s
->timer
= (double)temp_ref
*s
->h
.dwScale
/s
->h
.dwRate
;
306 default: // intra-coded
307 // pictires may be not in frame sequence so recalculate timer
308 pts
= (int)(90000*((double)temp_ref
*s
->h
.dwScale
/s
->h
.dwRate
)) + MPEG_STARTPTS
;
309 sz
= len
; // no extra buffer for it...
312 printf ("Unknown block type, possibly non-MPEG stream!\n");
317 } else { // MUXER_TYPE_AUDIO
318 if (len
< 2*MUXER_MPEG_DATASIZE
)
319 sz
= 2*MUXER_MPEG_DATASIZE
; // min requirement
323 mp_dbg(MSGT_MUXER
, MSGL_DBG3
, "\nMPEG chunk: size=%u, pts=%f", len
, s
->timer
);
324 set_mpeg_pts (muxer
, s
, pts
);
326 if (s
->h
.dwSampleSize
) {
328 s
->h
.dwLength
+= len
/s
->h
.dwSampleSize
;
329 if (len
%s
->h
.dwSampleSize
) printf("Warning! len isn't divisable by samplesize!\n");
334 if (!muxer
->sysrate
) {
335 muxer
->sysrate
= 2108000/8; // constrained stream parameter
336 muxer
->file_end
= MUXER_MPEG_BLOCKSIZE
*90000/muxer
->sysrate
+ MPEG_STARTSCR
+1;
338 if (sz
> s
->h
.dwSuggestedBufferSize
) { // increase and set STD
339 s
->h
.dwSuggestedBufferSize
= sz
;
340 if (s
->b_buffer
[2] != 0xff) // has both PTS and DTS
341 write_mpeg_std (s
->b_buffer
, s
->h
.dwSuggestedBufferSize
, 0x40); // 01
343 write_mpeg_std (s
->b_buffer
+5, s
->h
.dwSuggestedBufferSize
, 0x40); // 01
346 // write out block(s) if it's ready
347 while (s
->b_buffer_ptr
+len
>= MUXER_MPEG_DATASIZE
-12) { // reserved for std and pts
348 // write out the block
349 sz
= write_mpeg_block (muxer
, s
, f
, &s
->buffer
[ptr
], len
, 0);
350 // recalculate the rest of chunk
354 s
->timer
= (double)s
->h
.dwLength
*s
->h
.dwScale
/s
->h
.dwRate
;
355 if (len
) { // save rest in buffer
356 if (s
->b_buffer_ptr
== 0) {
357 memset (s
->b_buffer
, 0xff, 12); // stuFFing bytes for now
358 if (s
->type
== MUXER_TYPE_AUDIO
&& s
->h
.dwSampleSize
) { // CBR audio
359 sz
= s
->h
.dwLength
- len
/s
->h
.dwSampleSize
; // first sample number
360 write_mpeg_ts (s
->b_buffer
+7,
361 (int)(90000*((double)sz
*s
->h
.dwScale
/s
->h
.dwRate
)) + MPEG_STARTPTS
,
362 0x20); // 0010 and PTS only
364 s
->b_buffer_ptr
= 12;
366 memcpy (s
->b_buffer
+s
->b_buffer_ptr
, s
->buffer
+ptr
, len
);
367 s
->b_buffer_ptr
+= len
;
369 mp_dbg(MSGT_MUXER
, MSGL_DBG3
, " next pts=%f\n", s
->timer
);
372 static void mpegfile_write_header(muxer_t
*muxer
){
374 size_t sz
= MUXER_MPEG_BLOCKSIZE
-24;
375 unsigned char buff
[12];
376 muxer_stream_t
*s
= muxer
->streams
[0];
379 FILE *f
= muxer
->file
;
382 return; // no streams!?
383 // packet header (0x1ba) -- rewrite first stream buffer
384 *(uint32_t *)buff
= be2me_32 (0x1ba);
385 write_mpeg_ts (buff
+4, MPEG_STARTSCR
, 0x20); // 0010 -- pack
386 write_mpeg_rate (buff
+9, muxer
->sysrate
);
387 fwrite (buff
, 12, 1, f
);
388 // start system stream (in own block): Sys (0x1bb)
389 l1
= be2me_32 (0x1bb);
390 l2
= be2me_16 (6 + 3*muxer
->avih
.dwStreams
); // header_length
391 fwrite (&l1
, 4, 1, f
);
392 fwrite (&l2
, 2, 1, f
);
393 write_mpeg_rate (buff
, muxer
->sysrate
); // rate_bound
394 // set number of audio/video, fixed_flag=CSPS_flag=system_*_lock_flag=0
395 buff
[3] = (muxer
->avih
.dwStreams
- muxer
->num_videos
) << 2; // audio_bound
396 buff
[4] = muxer
->num_videos
| 0x20;
397 buff
[5] = 0xff; // reserved_byte
398 fwrite (buff
, 6, 1, f
);
399 for (i
= 0; i
< muxer
->avih
.dwStreams
; i
++) {
400 buff
[0] = ((char *)&muxer
->streams
[i
]->ckid
)[3]; // last char in big endian
401 //fprintf (stderr, "... stream 0x1%02x; bufsize %u", (int)buff[0], muxer->streams[i]->h.dwSuggestedBufferSize);
402 write_mpeg_std (buff
+1, muxer
->streams
[i
]->h
.dwSuggestedBufferSize
, 0xc0); // 11
403 fwrite (buff
, 3, 1, f
);
406 if (sz
>= 6) { // padding block
407 l1
= be2me_32 (0x1be);
410 fwrite (&l1
, 4, 1, f
);
411 fwrite (&l2
, 2, 1, f
);
413 s
->b_buffer
[0] = 0x0f; // end of list - next bit has to be 0
414 // stuFFing bytes -- rewrite first stream buffer
416 memset (s
->b_buffer
+1, 0xff, sz
-1);
417 fwrite (s
->b_buffer
, sz
, 1, f
);
418 muxer
->movi_start
= 0;
419 muxer
->movi_end
= MUXER_MPEG_BLOCKSIZE
;
422 static void mpegfile_write_index(muxer_t
*muxer
){
426 if (!muxer
->avih
.dwStreams
) return; // no streams?!
427 // finish all but one video and audio streams
428 rsr
= muxer
->sysrate
; // reserve it since it's silly change it at that point
429 for (i
= 0; i
< muxer
->avih
.dwStreams
-1; i
++)
430 write_mpeg_block (muxer
, muxer
->streams
[i
], muxer
->file
, NULL
, 0, 0);
431 // end sequence: ISO-11172-End (0x1b9) and finish very last block
432 write_mpeg_block (muxer
, muxer
->streams
[i
], muxer
->file
, NULL
, 0, 1);
433 //fprintf (stderr, "PTS to SCR delay: min %u.%03u, max %u.%03u\n",
434 // mpeg_min_delay/90000, (mpeg_min_delay/90)%1000,
435 // mpeg_max_delay/90000, (mpeg_max_delay/90)%1000);
436 muxer
->sysrate
= rsr
;
439 void muxer_init_muxer_mpeg(muxer_t
*muxer
){
440 muxer
->cont_new_stream
= &mpegfile_new_stream
;
441 muxer
->cont_write_chunk
= &mpegfile_write_chunk
;
442 muxer
->cont_write_header
= &mpegfile_write_header
;
443 muxer
->cont_write_index
= &mpegfile_write_index
;
444 // mpeg_min_delay = mpeg_max_delay = MPEG_STARTPTS-MPEG_STARTSCR;