Fix waveformatex size calculation
[mplayer.git] / libmpdemux / muxer_mpeg.c
blob2c40bc45dc8df6eedb0fdbcad26879af98789e2a
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/types.h>
7 #include "config.h"
8 #include "../version.h"
9 #include "../mp_msg.h"
11 #include "wine/mmreg.h"
12 #include "wine/avifmt.h"
13 #include "wine/vfw.h"
14 #include "bswap.h"
16 #include "muxer.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 */
25 // suggestions
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){
34 muxer_stream_t *s;
36 if (!muxer) return NULL;
37 if(muxer->avih.dwStreams>=MUXER_MAX_STREAMS){
38 printf("Too many streams! increase MUXER_MAX_STREAMS !\n");
39 return NULL;
41 switch (type) {
42 case MUXER_TYPE_VIDEO:
43 if (muxer->num_videos >= 15) {
44 printf ("MPEG stream can't contain above of 15 video streams!\n");
45 return NULL;
47 break;
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");
51 return NULL;
53 break;
54 default:
55 printf ("Unknown stream type!\n");
56 return NULL;
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))) {
62 free (s);
63 return NULL; // no mem?!
65 muxer->streams[muxer->avih.dwStreams]=s;
66 s->type=type;
67 s->id=muxer->avih.dwStreams;
68 s->timer=0.0;
69 s->size=0;
70 s->muxer=muxer;
71 if (type == MUXER_TYPE_VIDEO) {
72 s->ckid = be2me_32 (0x1e0 + muxer->num_videos);
73 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++;
83 return s;
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) {
95 if (rate)
96 rate--; // for round upward
97 rate /= 50;
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) {
105 if (size)
106 size--; // for round upward
107 if (size < (128 << 8))
108 size >>= 7; // by 128 bytes
109 else {
110 size >>= 10;
111 size |= 0x2000; // by 1kbyte
113 size++; // round upward
114 b[0] = ((size >> 8) & 0x3f) | 0x40 | mod;
115 b[1] = size & 0xff;
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;
122 uint16_t l1;
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;
127 s->b_buffer_ptr = 1;
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");
131 return 0;
132 } else {
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
137 if (len > sz)
138 len = sz;
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
145 sz -= len;
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
152 if (sz)
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
157 mints = 0;
158 else
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);
163 if (s->b_buffer_ptr)
164 fwrite (s->b_buffer+mints, s->b_buffer_ptr-mints, 1, f);
165 if (len)
166 fwrite (bl, len, 1, f);
167 if (sz > 6) { // padding block (0x1be)
168 uint32_t l0;
170 if (isoend)
171 l0 = be2me_32 (0x1b9);
172 else
173 l0 = be2me_32 (0x1be);
174 sz -= 6;
175 l1 = be2me_16 (sz);
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);
181 s->b_buffer_ptr = 0;
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
188 else
190 sz = 0;
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
214 return len;
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
227 if (pts) {
228 write_mpeg_ts (s->b_buffer+2, pts, 0x30); // 0011 and both PTS/DTS
229 } else {
230 write_mpeg_ts (s->b_buffer+7, dts, 0x20); // 0010 and PTS only
231 return;
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");
242 else
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){
249 size_t ptr=0, sz;
250 unsigned int pts=0;
251 muxer_t *muxer = s->muxer;
252 FILE *f;
254 f = muxer->file;
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");
258 sz = len;
259 // return;
260 } else if (s->buffer[3] == 0 || s->buffer[3] == 0xb3 ||
261 s->buffer[3] == 0xb8) { // Picture or GOP
262 int temp_ref;
263 int pt;
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);
273 if (ptr >= len-5) {
274 pt = 0; // Picture not found?!
275 temp_ref = 0;
276 printf ("Warning: picture not found in GOP!\n");
277 } else {
278 pt = (s->buffer[ptr+5]>>3) & 7;
279 temp_ref = (s->buffer[ptr+4]<<2)+(s->buffer[ptr+5]>>6);
281 ptr = 0;
282 temp_ref += s->gop_start;
283 switch (pt) {
284 case 2: // predictive
285 if (s->ipb[0]) {
286 sz = len + s->ipb[0];
287 if (s->ipb[0] < s->ipb[2])
288 s->ipb[0] = s->ipb[2];
289 s->ipb[2] = 0;
290 } else if (s->ipb[2]) {
291 sz = len + s->ipb[2];
292 s->ipb[0] = s->ipb[2];
293 s->ipb[2] = 0;
294 } else
295 sz = 4 * len; // no bidirectional frames yet?
296 s->ipb[1] = len;
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;
299 break;
300 case 3: // bidirectional
301 s->ipb[2] += len;
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;
305 break;
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...
311 } else {
312 printf ("Unknown block type, possibly non-MPEG stream!\n");
313 sz = len;
314 // return;
316 sz <<= 1;
317 } else { // MUXER_TYPE_AUDIO
318 if (len < 2*MUXER_MPEG_DATASIZE)
319 sz = 2*MUXER_MPEG_DATASIZE; // min requirement
320 else
321 sz = len;
323 mp_dbg(MSGT_MUXER, MSGL_DBG3, "\nMPEG chunk: size=%u, pts=%f", len, s->timer);
324 set_mpeg_pts (muxer, s, pts);
325 // alter counters:
326 if (s->h.dwSampleSize) {
327 // CBR
328 s->h.dwLength += len/s->h.dwSampleSize;
329 if (len%s->h.dwSampleSize) printf("Warning! len isn't divisable by samplesize!\n");
330 } else {
331 // VBR
332 s->h.dwLength++;
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
342 else // has only PTS
343 write_mpeg_std (s->b_buffer+5, s->h.dwSuggestedBufferSize, 0x40); // 01
345 s->size += len;
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
351 ptr += sz;
352 len -= sz;
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){
373 unsigned int i;
374 size_t sz = MUXER_MPEG_BLOCKSIZE-24;
375 unsigned char buff[12];
376 muxer_stream_t *s = muxer->streams[0];
377 uint32_t l1;
378 uint16_t l2;
379 FILE *f = muxer->file;
381 if (s == NULL)
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);
404 sz -= 3;
406 if (sz >= 6) { // padding block
407 l1 = be2me_32 (0x1be);
408 sz -= 6;
409 l2 = be2me_16 (sz);
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
415 if (sz > 1)
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){
423 unsigned int i;
424 unsigned int rsr;
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;