1 /*
2  * pes.c: MPEG PES functions for replex
3  *
4  *
5  * Copyright (C) 2003 - 2006
6  *                    Marcus Metzler <mocm@metzlerbros.de>
7  *                    Metzler Brothers Systementwicklung GbR
8  *           (C) 2006 Reel Multimedia
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * General Public License for more details.
20  *
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
26  *
27  */
28 
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <netinet/in.h>
33 #include <string.h>
34 
35 #include "pes.h"
36 
37 //#define PES_DEBUG
38 
printpts(int64_t pts)39 void printpts(int64_t pts)
40 {
41 	if (pts < 0){
42 		fprintf(stderr,"-");
43 		pts = -pts;
44 	}
45 	pts = pts/300;
46 	pts &= (MAX_PTS-1);
47 	fprintf(stderr,"%2d:%02d:%02d.%03d ",
48 		(unsigned int)(pts/90000.)/3600,
49 		((unsigned int)(pts/90000.)%3600)/60,
50 		((unsigned int)(pts/90000.)%3600)%60,
51 		(((unsigned int)(pts/90.)%3600000)%60000)%1000
52 		);
53 }
54 
printptss(int64_t pts)55 void printptss(int64_t pts)
56 {
57 	if (pts < 0){
58 		fprintf(stdout,"-");
59 		pts = -pts;
60 	}
61 	pts = pts/300;
62 	pts &= (MAX_PTS-1);
63 	fprintf(stdout,"%2d:%02d:%02d.%03d ",
64 		(unsigned int)(pts/90000.)/3600,
65 		((unsigned int)(pts/90000.)%3600)/60,
66 		((unsigned int)(pts/90000.)%3600)%60,
67 		(((unsigned int)(pts/90.)%3600000)%60000)%1000
68 		);
69 }
70 
71 /* use if you know that ptss are close and may overflow */
ptsdiff(uint64_t pts1,uint64_t pts2)72 int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
73 {
74 	switch (ptscmp(pts1, pts2)){
75 	case 0:
76 		return 0;
77 		break;
78 
79 	case 1:
80 	case -2:
81 		return (pts1 -pts2);
82 		break;
83 
84 	case 2:
85 		return (pts1 + MAX_PTS2 -pts2);
86 		break;
87 
88 	case -1:
89 		return (pts1 - (pts2+ MAX_PTS2));
90 		break;
91 
92 	}
93 
94 	return 0;
95 }
96 
97 /* use, if you need  an unsigned result in pts range */
uptsdiff(uint64_t pts1,uint64_t pts2)98 uint64_t uptsdiff(uint64_t pts1, uint64_t pts2)
99 {
100 	int64_t diff;
101 
102 	diff = pts1 - pts2;
103 
104 	if (diff < 0){
105 		diff = MAX_PTS2 +diff;
106 	}
107 	return diff;
108 }
109 
ptscmp(uint64_t pts1,uint64_t pts2)110 int ptscmp(uint64_t pts1, uint64_t pts2)
111 {
112 	int ret;
113 
114 	if (pts1 > pts2){
115 		if ((pts1 - pts2) > MAX_PTS2/2)
116 			ret = -1;
117 		else
118 			ret = 1;
119 	} else if (pts1 == pts2) ret = 0;
120 	else {
121 		if ((pts2 - pts1) > MAX_PTS2/2)
122 			ret = 2;
123 		else
124 			ret = -2;
125 	}
126 /*
127 	fprintf(stderr,"PTSCMP: %lli %lli %d\n", pts1, pts2, ret);
128 	printpts(pts1);
129 	printpts(pts2);
130 	fprintf(stderr,"\n");
131 */
132 	return ret;
133 }
134 
ptsadd(uint64_t pts1,uint64_t pts2)135 uint64_t ptsadd(uint64_t pts1, uint64_t pts2)
136 {
137 	ptsinc(&pts1,pts2);
138 	return pts1;
139 
140 }
141 
init_pes_in(pes_in_t * p,int t,ringbuffer * rb,int wi)142 void init_pes_in(pes_in_t *p, int t, ringbuffer *rb, int wi){
143 	p->type = t;
144         p->found = 0;
145         p->cid = 0;
146         p->mpeg = 0;
147 	p->withbuf = wi;
148 
149 	if (p->withbuf && !p->buf){
150 		p->buf = malloc(MAX_PLENGTH*sizeof(uint8_t));
151 		memset(p->buf,0,MAX_PLENGTH*sizeof(uint8_t));
152 	} else if (rb) p->rbuf = rb;
153 	if (p->rbuf) p->ini_pos = ring_wpos(p->rbuf);
154         p->done = 0;
155 	memset(p->pts, 0 , 5);
156 	memset(p->dts, 0 , 5);
157 }
158 
159 
get_pes(pes_in_t * p,uint8_t * buf,int count,void (* func)(pes_in_t * p))160 void get_pes (pes_in_t *p, uint8_t *buf, int count, void (*func)(pes_in_t *p))
161 {
162 
163 	int l=0;
164 	unsigned short *pl=NULL;
165 	int c=0;
166 
167 	uint8_t headr[3] = { 0x00, 0x00, 0x01} ;
168 	while (c < count && (!p->mpeg ||
169 			     (p->mpeg == 2 && p->found < 9))
170 	       &&  (p->found < 5 || !p->done)){
171 		switch ( p->found ){
172 		case 0:
173 		case 1:
174 			if (buf[c] == 0x00) p->found++;
175 			else p->found = 0;
176 			c++;
177 			break;
178 		case 2:
179 			if (buf[c] == 0x01) p->found++;
180 			else if (buf[c] == 0){
181 				p->found = 2;
182 			} else p->found = 0;
183 			c++;
184 			break;
185 		case 3:
186 			p->cid = 0;
187 			switch (buf[c]){
188 			case PROG_STREAM_MAP:
189 			case PRIVATE_STREAM2:
190 			case PROG_STREAM_DIR:
191 			case ECM_STREAM     :
192 			case EMM_STREAM     :
193 			case PADDING_STREAM :
194 			case DSM_CC_STREAM  :
195 			case ISO13522_STREAM:
196 				p->done = 1;
197 			case PRIVATE_STREAM1:
198 			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
199 			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
200 				p->found++;
201 				p->cid = buf[c];
202 				c++;
203 				break;
204 			default:
205 			case PACK_START:
206 			case SYS_START:
207 				p->found = 0;
208 				c++;
209 				break;
210 			}
211 			break;
212 
213 
214 		case 4:
215 			if (count-c > 1){
216 				pl = (unsigned short *) (buf+c);
217 				p->plength =  ntohs(*pl);
218 				p->plen[0] = buf[c];
219 				c++;
220 				p->plen[1] = buf[c];
221 				c++;
222 				p->found+=2;
223 			} else {
224 				p->plen[0] = buf[c];
225 				p->found++;
226 				return;
227 			}
228 			break;
229 		case 5:
230 			p->plen[1] = buf[c];
231 			c++;
232 			pl = (unsigned short *) p->plen;
233 			p->plength = ntohs(*pl);
234 			p->found++;
235 			break;
236 
237 
238 		case 6:
239 			if (!p->done){
240 				p->flag1 = buf[c];
241 				c++;
242 				p->found++;
243 				if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
244 				else {
245 					fprintf(stderr, "Error in PES Header 0x%2x\n",p->cid);
246 					p->found = 0;
247 				}
248 			}
249 			break;
250 
251 		case 7:
252 			if ( !p->done && p->mpeg == 2){
253 				p->flag2 = buf[c];
254 				c++;
255 				p->found++;
256 			}
257 			break;
258 
259 		case 8:
260 			if ( !p->done && p->mpeg == 2){
261 				p->hlength = buf[c];
262 				c++;
263 				p->found++;
264 			}
265 			break;
266 
267 		default:
268 
269 			break;
270 		}
271 		if(p->plength && p->found == 9 && p->found > p->plength+6){
272 			fprintf(stderr, "Error in PES Header 0x%2x\n",p->cid);
273 			p->found = 0;
274 		}
275 	}
276 
277 	if (!p->plength) p->plength = MMAX_PLENGTH-6;
278 
279 
280 	if ( p->done || (p->mpeg == 2 && p->found >= 9) ){
281 		switch (p->cid){
282 
283 		case AUDIO_STREAM_S ... AUDIO_STREAM_E:
284 		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
285 		case PRIVATE_STREAM1:
286 
287 			if (p->withbuf){
288 				memcpy(p->buf, headr, 3);
289 				p->buf[3] = p->cid;
290 				memcpy(p->buf+4,p->plen,2);
291 			} else {
292 				memcpy(p->hbuf, headr, 3);
293 				p->hbuf[3] = p->cid;
294 				memcpy(p->hbuf+4,p->plen,2);
295 			}
296 
297 			if (p->found == 9){
298 				if (p->withbuf){
299 					p->buf[6] = p->flag1;
300 					p->buf[7] = p->flag2;
301 					p->buf[8] = p->hlength;
302 				} else {
303 					p->hbuf[6] = p->flag1;
304 					p->hbuf[7] = p->flag2;
305 					p->hbuf[8] = p->hlength;
306 				}
307 			}
308 
309 			if ( (p->flag2 & PTS_ONLY) &&  p->found < 14){
310 				while (c < count && p->found < 14){
311 					p->pts[p->found-9] = buf[c];
312 					if (p->withbuf)
313 						p->buf[p->found] = buf[c];
314 					else
315 						p->hbuf[p->found] = buf[c];
316 					c++;
317 					p->found++;
318 				}
319 				if (c == count) return;
320 			}
321 
322 			if (((p->flag2 & PTS_DTS) == 0xC0) && p->found < 19){
323 				while (c < count && p->found < 19){
324 					p->dts[p->found-14] = buf[c];
325 					if (p->withbuf)
326 						p->buf[p->found] = buf[c];
327 					else
328 						p->hbuf[p->found] = buf[c];
329 					c++;
330 					p->found++;
331 				}
332 				if (c == count) return;
333 			}
334 
335 
336 			while (c < count && p->found < p->plength+6){
337 				l = count -c;
338 				if (l+p->found > p->plength+6)
339 					l = p->plength+6-p->found;
340 				if (p->withbuf)
341 					memcpy(p->buf+p->found, buf+c, l);
342 				else {
343 					if ( p->found < p->hlength+9 ){
344 						int rest = p->hlength+9-p->found;
345 						memcpy(p->hbuf+p->found, buf+c, rest);
346 						if (ring_write(p->rbuf, buf+c+rest,
347 							       l-rest) <0){
348 							fprintf(stderr,
349 								"ring buffer overflow in get_pes %d\n"
350 								,p->rbuf->size);
351 							exit(1);
352 						}
353 					} else {
354 						if (ring_write(p->rbuf, buf+c, l)<0){
355 							fprintf(stderr,
356 								"ring buffer overflow in get_pes %d\n"
357 								,p->rbuf->size);
358 							exit(1);
359 						}
360 					}
361 				}
362 
363 				p->found += l;
364 				c += l;
365 			}
366 			if(p->found == p->plength+6){
367 				func(p);
368 			}
369 			break;
370 		}
371 
372 		if ( p->done ){
373 			if( p->found + count - c < p->plength+6){
374 				p->found += count-c;
375 				c = count;
376 			} else {
377 				c += p->plength+6 - p->found;
378 				p->found = p->plength+6;
379 			}
380 		}
381 
382 		if (p->plength && p->found == p->plength+6) {
383 			init_pes_in(p, p->type, NULL, p->withbuf);
384 			if (c < count)
385 				get_pes(p, buf+c, count-c, func);
386 		}
387 	}
388 	return;
389 }
390 
391 
scr_base_ps(uint8_t * scr)392 uint32_t scr_base_ps(uint8_t *scr)
393 {
394 	uint32_t base = 0;
395 	uint8_t *buf = (uint8_t *)&base;
396 
397 	buf[0] |= (uint8_t)((scr[0] & 0x18) << 3);
398 	buf[0] |= (uint8_t)((scr[0] & 0x03) << 4);
399 	buf[0] |= (uint8_t)((scr[1] & 0xF0) >> 4);
400 
401 	buf[1] |= (uint8_t)((scr[1] & 0x0F) << 4);
402 	buf[1] |= (uint8_t)((scr[2] & 0xF0) >> 4);
403 
404 	buf[2] |= (uint8_t)((scr[2] & 0x08) << 4);
405 	buf[2] |= (uint8_t)((scr[2] & 0x03) << 5);
406 	buf[2] |= (uint8_t)((scr[3] & 0xF8) >> 3);
407 
408 	buf[3] |= (uint8_t)((scr[3] & 0x07) << 5);
409 	buf[3] |= (uint8_t)((scr[4] & 0xF8) >> 3);
410 
411 	base = ntohl(base);
412 	return base;
413 }
414 
scr_ext_ps(uint8_t * scr)415 uint16_t scr_ext_ps(uint8_t *scr)
416 {
417 	short ext = 0;
418 
419 	ext = (short)(scr[5] >> 1);
420 	ext += (short) (scr[4] &  0x03) * 128;
421 
422 	return ext;
423 }
424 
425 
426 
init_ps(ps_packet * p)427 void init_ps(ps_packet *p)
428 {
429         p->stuff_length=0xF8;
430         p->data = NULL;
431         p->sheader_length = 0;
432         p->audio_bound = 0;
433         p->video_bound = 0;
434         p->npes = 0;
435 }
436 
kill_ps(ps_packet * p)437 void kill_ps(ps_packet *p)
438 {
439         if (p->data)
440                 free(p->data);
441         init_ps(p);
442 }
443 
setlength_ps(ps_packet * p)444 void setlength_ps(ps_packet *p)
445 {
446         short *ll;
447         ll = (short *) p->sheader_llength;
448 	p->sheader_length = ntohs(*ll) - 6;
449 }
450 
setl_ps(ps_packet * p)451 static void setl_ps(ps_packet *p)
452 {
453         setlength_ps(p);
454         p->data = (uint8_t *) malloc(p->sheader_length);
455 }
456 
457 
cwrite_ps(uint8_t * buf,ps_packet * p,uint32_t length)458 int cwrite_ps(uint8_t *buf, ps_packet *p, uint32_t length)
459 {
460         long count,i;
461         uint8_t headr1[4] = {0x00, 0x00, 0x01, PACK_START };
462         uint8_t headr2[4] = {0x00, 0x00, 0x01, SYS_START };
463         uint8_t buffy = 0xFF;
464 
465 
466         memcpy(buf,headr1,4);
467         count = 4;
468 	memcpy(buf+count,p->scr,6);
469 	count += 6;
470 	memcpy(buf+count,p->mux_rate,3);
471 	count += 3;
472 	memcpy(buf+count,&p->stuff_length,1);
473 	count++;
474 	for(i=0; i< (p->stuff_length & 3); i++){
475 		memcpy(buf+count,&buffy,1);
476 		count++;
477 	}
478 
479         if (p->sheader_length){
480                 memcpy(buf+count,headr2,4);
481                 count += 4;
482                 memcpy(buf+count,p->sheader_llength,2);
483                 count += 2;
484 		memcpy(buf+count,p->rate_bound,3);
485 		count += 3;
486 		memcpy(buf+count,&p->audio_bound,1);
487 		count++;
488 		memcpy(buf+count,&p->video_bound,1);
489 		count++;
490 		memcpy(buf+count,&p->reserved,1);
491 		count++;
492                 memcpy(buf+count,p->data,p->sheader_length);
493                 count += p->sheader_length;
494         }
495 
496         return count;
497 }
498 
499 
500 
write_ps_header(uint8_t * buf,uint64_t SCR,uint32_t muxr,uint8_t audio_bound,uint8_t fixed,uint8_t CSPS,uint8_t audio_lock,uint8_t video_lock,uint8_t video_bound,uint8_t navpack)501 int write_ps_header(uint8_t *buf,
502 		    uint64_t   SCR,
503 		    uint32_t   muxr,
504 		    uint8_t    audio_bound,
505 		    uint8_t    fixed,
506 		    uint8_t    CSPS,
507 		    uint8_t    audio_lock,
508 		    uint8_t    video_lock,
509 		    uint8_t    video_bound,
510 		    uint8_t    navpack)
511 {
512 	ps_packet p;
513 	uint8_t *scr;
514 	uint32_t lscr;
515 	uint16_t scr_ext = 0;
516 
517 	init_ps(&p);
518 
519 	lscr = htonl((uint32_t) ((SCR/300ULL) & 0x00000000FFFFFFFF));
520 	scr = (uint8_t *) &lscr;
521 	scr_ext = (uint16_t) ((SCR%300ULL) & 0x00000000000001FF);
522 
523 // SCR = 0
524 	p.scr[0] = 0x44;
525 	p.scr[1] = 0x00;
526 	p.scr[2] = 0x04;
527 	p.scr[3] = 0x00;
528 	p.scr[4] = 0x04;
529 	p.scr[5] = 0x01;
530 
531 	p.scr[0] = 0x44 | ((scr[0] >> 3)&0x18) | ((scr[0] >> 4)&0x03);
532 	p.scr[1] = 0x00 | ((scr[0] << 4)&0xF0) | ((scr[1] >> 4)&0x0F);
533 	p.scr[2] = 0x04 | ((scr[1] << 4)&0xF0) | ((scr[2] >> 4)&0x08)
534 		| ((scr[2] >> 5)&0x03);
535 	p.scr[3] = 0x00 | ((scr[2] << 3)&0xF8) | ((scr[3] >> 5)&0x07);
536 	p.scr[4] = 0x04 | ((scr[3] << 3)&0xF8) | ((scr_ext >> 7)&0x03);
537 	p.scr[5] = 0x01 | ((scr_ext << 1)&0xFF);
538 
539 
540 	muxr = muxr/50;
541 	p.mux_rate[0] = (uint8_t)(muxr >> 14);
542 	p.mux_rate[1] = (uint8_t)(0xff & (muxr >> 6));
543 	p.mux_rate[2] = (uint8_t)(0x03 | ((muxr & 0x3f) << 2));
544 
545 	p.stuff_length = 0xF8;
546 
547 	if (navpack){
548 		p.sheader_llength[0] = 0x00;
549 		p.sheader_llength[1] = 0x12;
550 
551 		setl_ps(&p);
552 
553 		p.rate_bound[0] = (uint8_t)(0x80 | (muxr >>15));
554 		p.rate_bound[1] = (uint8_t)(0xff & (muxr >> 7));
555 		p.rate_bound[2] = (uint8_t)(0x01 | ((muxr & 0x7f)<<1));
556 
557 		p.audio_bound = (uint8_t)((audio_bound << 2)|(fixed << 1)|CSPS);
558 		p.video_bound = (uint8_t)((audio_lock << 7)|
559 				     (video_lock << 6)|0x20|video_bound);
560 		p.reserved = (uint8_t)(0xFF >> 1);
561 
562 		p.data[0] = 0xB9;
563 		p.data[1] = 0xE0;
564 		p.data[2] = 0xE8;
565 		p.data[3] = 0xB8;
566 		p.data[4] = 0xC0;
567 		p.data[5] = 0x20;
568 		p.data[6] = 0xbd;
569 		p.data[7] = 0xe0;
570 		p.data[8] = 0x3a;
571 		p.data[9] = 0xBF;
572 		p.data[10] = 0xE0;
573 		p.data[11] = 0x02;
574 
575 		cwrite_ps(buf, &p, PS_HEADER_L2);
576 		kill_ps(&p);
577 		return PS_HEADER_L2;
578 	} else {
579 		cwrite_ps(buf, &p, PS_HEADER_L1);
580 		kill_ps(&p);
581 		return PS_HEADER_L1;
582 	}
583 }
584 
585 
get_pespts(uint8_t * spts,uint8_t * pts)586 void get_pespts(uint8_t *spts,uint8_t *pts)
587 {
588 
589         pts[0] = 0x21 |
590                 ((spts[0] & 0xC0) >>5);
591         pts[1] = ((spts[0] & 0x3F) << 2) |
592                 ((spts[1] & 0xC0) >> 6);
593         pts[2] = 0x01 | ((spts[1] & 0x3F) << 2) |
594                 ((spts[2] & 0x80) >> 6);
595         pts[3] = ((spts[2] & 0x7F) << 1) |
596                 ((spts[3] & 0x80) >> 7);
597         pts[4] = 0x01 | ((spts[3] & 0x7F) << 1);
598 }
599 
write_pes_header(uint8_t id,int length,uint64_t PTS,uint64_t DTS,uint8_t * obuf,int stuffing,uint8_t ptsdts)600 int write_pes_header(uint8_t id, int length , uint64_t PTS, uint64_t DTS,
601 		     uint8_t *obuf, int stuffing, uint8_t ptsdts)
602 {
603 	uint8_t le[2];
604 	uint8_t dummy[3];
605 	uint8_t *pts;
606 	uint8_t ppts[5];
607 	uint32_t lpts;
608 	uint8_t *dts;
609 	uint8_t pdts[5];
610 	uint32_t ldts;
611 	int c;
612 	uint8_t headr[3] = {0x00, 0x00, 0x01};
613 
614 	lpts = htonl((PTS/300ULL) & 0x00000000FFFFFFFFULL);
615 	pts = (uint8_t *) &lpts;
616 	get_pespts(pts,ppts);
617 	if ((PTS/300ULL) & 0x0000000100000000ULL) ppts[0] |= 0x80;
618 
619 	ldts = htonl((DTS/300ULL) & 0x00000000FFFFFFFFULL);
620 	dts = (uint8_t *) &ldts;
621 	get_pespts(dts,pdts);
622 	if ((DTS/300ULL) & 0x0000000100000000ULL) pdts[0] |= 0x80;
623 
624 	c = 0;
625 	memcpy(obuf+c,headr,3);
626 	c += 3;
627 	memcpy(obuf+c,&id,1);
628 	c++;
629 
630 	le[0] = 0;
631 	le[1] = 0;
632 	length -= 6;
633 
634 	le[0] |= ((uint8_t)(length >> 8) & 0xFF);
635 	le[1] |= ((uint8_t)(length) & 0xFF);
636 	memcpy(obuf+c,le,2);
637 	c += 2;
638 
639 	if (id == PADDING_STREAM){
640 		memset(obuf+c,0xff,length);
641 		c+= length;
642 		return c;
643 	}
644 
645 	dummy[0] = 0x80;
646 	dummy[1] = 0;
647 	dummy[2] = 0;
648 
649 	if (ptsdts == PTS_ONLY){
650 		dummy[2] = 5 + stuffing;
651 		dummy[1] |= PTS_ONLY;
652 	} else 	if (ptsdts == PTS_DTS){
653 		dummy[2] = 10 + stuffing;
654 		dummy[1] |= PTS_DTS;
655 	}
656 
657 	memcpy(obuf+c,dummy,3);
658 	c += 3;
659 
660 	memset(obuf+c,0xFF,stuffing);
661 	c += stuffing;
662 
663 	if (ptsdts == PTS_ONLY){
664 		memcpy(obuf+c,ppts,5);
665 		c += 5;
666 	} else if ( ptsdts == PTS_DTS ){
667 		memcpy(obuf+c,ppts,5);
668 		c += 5;
669 		memcpy(obuf+c,pdts,5);
670 		c += 5;
671 	}
672 	return c;
673 }
674 
write_padding_pes(int pack_size,int apidn,int ac3n,uint64_t SCR,uint64_t muxr,uint8_t * buf)675 void write_padding_pes( int pack_size, int apidn, int ac3n,
676 			uint64_t SCR, uint64_t muxr, uint8_t *buf)
677 {
678 	int pos = 0;
679 
680 	pos = write_ps_header(buf,SCR,muxr, apidn+ ac3n, 0, 0, 1, 1, 1,
681 			      0);
682 
683 	pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0, 0, buf+pos,
684 				 0, 0);
685 
686 }
687 
write_video_pes(int pack_size,int apidn,int ac3n,uint64_t vpts,uint64_t vdts,uint64_t SCR,uint64_t muxr,uint8_t * buf,int * vlength,uint8_t ptsdts,ringbuffer * vrbuffer)688 int write_video_pes( int pack_size, int apidn, int ac3n, uint64_t vpts,
689 		     uint64_t vdts, uint64_t SCR, uint64_t muxr,
690 		     uint8_t *buf, int *vlength,
691 		     uint8_t ptsdts, ringbuffer *vrbuffer)
692 {
693 	int add;
694 	int pos = 0;
695 	int p   = 0;
696 	int stuff = 0;
697 	int length = *vlength;
698 
699 #ifdef PES_DEBUG
700 	fprintf(stderr,"write video PES ");
701 	printpts(vdts);
702 	fprintf(stderr,"\n");
703 #endif
704 	if (! length) return 0;
705 	p = PS_HEADER_L1+PES_H_MIN;
706 
707 	if ( ptsdts == PTS_ONLY){
708 		p += 5;
709 	} else if (ptsdts == PTS_DTS){
710 		p += 10;
711 	}
712 
713 	if ( length+p >= pack_size){
714 		length = pack_size;
715 	} else {
716 		if (pack_size - length - p <= PES_MIN){
717 			stuff = pack_size - length-p;
718 			length = pack_size;
719 		} else
720 			length = length+p;
721 	}
722 
723 	pos = write_ps_header(buf,SCR,muxr, apidn+ac3n, 0, 0, 1, 1,
724 			      1, 0);
725 
726 	pos += write_pes_header( 0xE0, length-pos, vpts, vdts, buf+pos,
727 				 stuff, ptsdts);
728 	if (length-pos > *vlength){
729 		fprintf(stderr,"WHAT THE HELL  %d > %d\n", length-pos,
730 			*vlength);
731 	}
732 
733 	add = ring_read( vrbuffer, buf+pos, length-pos);
734 	*vlength = add;
735 	if (add < 0) return -1;
736 	pos += add;
737 
738 	if (pos+PES_MIN < pack_size){
739 		pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0, 0,
740 					 buf+pos, 0, 0);
741 		pos = pack_size;
742 	}
743 	return pos;
744 }
745 
write_audio_pes(int pack_size,int apidn,int ac3n,int n,uint64_t pts,uint64_t SCR,uint32_t muxr,uint8_t * buf,int * alength,uint8_t ptsdts,ringbuffer * arbuffer)746 int write_audio_pes(  int pack_size, int apidn, int ac3n, int n, uint64_t pts,
747 		      uint64_t SCR, uint32_t muxr, uint8_t *buf, int *alength,
748 		      uint8_t ptsdts, 	ringbuffer *arbuffer)
749 {
750 	int add;
751 	int pos = 0;
752 	int p   = 0;
753 	int stuff = 0;
754 	int length = *alength;
755 
756 #ifdef PES_DEBUG
757 	fprintf(stderr,"write audio PES ");
758 	printpts(pts);
759 	fprintf(stderr,"\n");
760 #endif
761 
762 	if (!length) return 0;
763 	p = PS_HEADER_L1+PES_H_MIN;
764 
765 	if (ptsdts == PTS_ONLY){
766 		p += 5;
767 	}
768 
769 	if ( length+p >= pack_size){
770 		length = pack_size;
771 	} else {
772 		if (pack_size-length-p <= PES_MIN){
773 			stuff = pack_size - length-p;
774 			length = pack_size;
775 		} else
776 			length = length+p;
777 	}
778 	pos = write_ps_header(buf,SCR,muxr, apidn + ac3n, 0, 0, 1, 1,
779 			      1, 0);
780 	pos += write_pes_header( 0xC0+n, length-pos, pts, 0, buf+pos, stuff,
781 				 ptsdts);
782 	add = ring_read( arbuffer, buf+pos, length-pos);
783 	*alength = add;
784 	if (add < 0) return -1;
785 	pos += add;
786 
787 	if (pos+PES_MIN < pack_size){
788 		pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
789 					 buf+pos, 0, 0);
790 		pos = pack_size;
791 	}
792 	if (pos != pack_size) {
793 		fprintf(stderr,"apos: %d\n",pos);
794 		exit(1);
795 	}
796 
797 	return pos;
798 }
799 
800 
801 
write_ac3_pes(int pack_size,int apidn,int ac3n,int n,uint64_t pts,uint64_t SCR,uint32_t muxr,uint8_t * buf,int * alength,uint8_t ptsdts,int nframes,int ac3_off,ringbuffer * ac3rbuffer,int framelength)802 int write_ac3_pes(  int pack_size, int apidn, int ac3n, int n,
803 		    uint64_t pts, uint64_t SCR,
804 		    uint32_t muxr, uint8_t *buf, int *alength, uint8_t ptsdts,
805 		    int nframes,int ac3_off, ringbuffer *ac3rbuffer, int framelength)
806 {
807 	int add;
808 	int pos = 0;
809 	int p   = 0;
810 	int stuff = 0;
811 	int length = *alength;
812 
813 #ifdef PES_DEBUG
814 	fprintf(stderr,"write ac3 PES ");
815 	printpts(pts);
816 	fprintf(stderr,"\n");
817 #endif
818 
819 	if (!length) return 0;
820 	p = PS_HEADER_L1+PES_H_MIN;
821 
822 	if (ptsdts == PTS_ONLY){
823 		p += 5;
824 	}
825 
826 	if ( length+p >= pack_size){
827 		if (length+p -pack_size == framelength-4) nframes--;
828 		length = pack_size;
829 	} else {
830 		if (pack_size-length-p <= PES_MIN){
831 			stuff = pack_size - length-p;
832 			length = pack_size;
833 		} else
834 			length = length+p;
835 	}
836 	pos = write_ps_header(buf,SCR,muxr, apidn+ac3n, 0, 0, 1, 1,
837 			      1, 0);
838 
839 	pos += write_pes_header( PRIVATE_STREAM1, length-pos, pts, 0,
840 				 buf+pos, stuff, ptsdts);
841 	buf[pos] = 0x80 + n +apidn;
842 	buf[pos+1] = nframes;
843 	buf[pos+2] = (ac3_off >> 8)& 0xFF;
844 	buf[pos+3] = (ac3_off)& 0xFF;
845 	pos += 4;
846 
847 	add = ring_read( ac3rbuffer, buf+pos, length-pos);
848 	*alength = add;
849 	if (add < 0) return -1;
850 	pos += add;
851 
852 	if (pos+PES_MIN < pack_size){
853 		pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
854 					 buf+pos, 0, 0);
855 		pos = pack_size;
856 	}
857 	if (pos != pack_size) {
858 		fprintf(stderr,"apos: %d\n",pos);
859 		exit(1);
860 	}
861 
862 	return pos;
863 }
864 
865 
bwrite_audio_pes(int pack_size,int apidn,int ac3n,int n,uint64_t pts,uint64_t SCR,uint32_t muxr,uint8_t * buf,int * alength,uint8_t ptsdts,uint8_t * arbuffer,int bsize)866 int bwrite_audio_pes(  int pack_size, int apidn, int ac3n, int n, uint64_t pts,
867 		      uint64_t SCR, uint32_t muxr, uint8_t *buf, int *alength,
868 		       uint8_t ptsdts, uint8_t *arbuffer, int bsize )
869 {
870 	int add;
871 	int pos = 0;
872 	int p   = 0;
873 	int stuff = 0;
874 	int length = *alength;
875 
876 #ifdef PES_DEBUG
877 	fprintf(stderr,"write audio PES ");
878 	printpts(pts);
879 	fprintf(stderr,"\n");
880 #endif
881 
882 	if (!length) return 0;
883 	p = PS_HEADER_L1+PES_H_MIN;
884 
885 	if (ptsdts == PTS_ONLY){
886 		p += 5;
887 	}
888 
889 	if ( length+p >= pack_size){
890 		length = pack_size;
891 	} else {
892 		if (pack_size-length-p <= PES_MIN){
893 			stuff = pack_size - length-p;
894 			length = pack_size;
895 		} else
896 			length = length+p;
897 	}
898 	pos = write_ps_header(buf,SCR,muxr, apidn + ac3n, 0, 0, 1, 1,
899 			      1, 0);
900 	pos += write_pes_header( 0xC0+n, length-pos, pts, 0, buf+pos, stuff,
901 				 ptsdts);
902 
903 	if (length -pos < bsize){
904 		memcpy(buf+pos, arbuffer, length-pos);
905 		add = length - pos;
906 		*alength = add;
907 	} else  return -1;
908 
909 	pos += add;
910 
911 	if (pos+PES_MIN < pack_size){
912 		pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
913 					 buf+pos, 0, 0);
914 		pos = pack_size;
915 	}
916 	if (pos != pack_size) {
917 		fprintf(stderr,"apos: %d\n",pos);
918 		exit(1);
919 	}
920 
921 	return pos;
922 }
923 
924 
925 
bwrite_ac3_pes(int pack_size,int apidn,int ac3n,int n,uint64_t pts,uint64_t SCR,uint32_t muxr,uint8_t * buf,int * alength,uint8_t ptsdts,int nframes,int ac3_off,uint8_t * ac3rbuffer,int bsize,int framelength)926 int bwrite_ac3_pes(  int pack_size, int apidn, int ac3n, int n,
927 		    uint64_t pts, uint64_t SCR,
928 		    uint32_t muxr, uint8_t *buf, int *alength, uint8_t ptsdts,
929 		     int nframes,int ac3_off, uint8_t *ac3rbuffer, int bsize, int framelength)
930 {
931 	int add;
932 	int pos = 0;
933 	int p   = 0;
934 	int stuff = 0;
935 	int length = *alength;
936 
937 #ifdef PES_DEBUG
938 	fprintf(stderr,"write ac3 PES ");
939 	printpts(pts);
940 	fprintf(stderr,"\n");
941 #endif
942 	if (!length) return 0;
943 	p = PS_HEADER_L1+PES_H_MIN;
944 
945 	if (ptsdts == PTS_ONLY){
946 		p += 5;
947 	}
948 
949 	if ( length+p >= pack_size){
950 		if (length+p -pack_size == framelength-4) nframes--;
951 		length = pack_size;
952 	} else {
953 		if (pack_size-length-p <= PES_MIN){
954 			stuff = pack_size - length-p;
955 			length = pack_size;
956 		} else
957 			length = length+p;
958 	}
959 	pos = write_ps_header(buf,SCR,muxr, apidn+ac3n, 0, 0, 1, 1,
960 			      1, 0);
961 
962 	pos += write_pes_header( PRIVATE_STREAM1, length-pos, pts, 0,
963 				 buf+pos, stuff, ptsdts);
964 	buf[pos] = 0x80 + n +apidn;
965 	buf[pos+1] = nframes;
966 	buf[pos+2] = (ac3_off >> 8)& 0xFF;
967 	buf[pos+3] = (ac3_off)& 0xFF;
968 	pos += 4;
969 
970 	if (length-pos <= bsize){
971 		memcpy(buf+pos, ac3rbuffer, length-pos);
972 		add = length-pos;
973 		*alength = add;
974 	} else return -1;
975 	pos += add;
976 
977 	if (pos+PES_MIN < pack_size){
978 		pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
979 					 buf+pos, 0, 0);
980 		pos = pack_size;
981 	}
982 	if (pos != pack_size) {
983 		fprintf(stderr,"apos: %d\n",pos);
984 		exit(1);
985 	}
986 
987 	return pos;
988 }
989 
990 
write_nav_pack(int pack_size,int apidn,int ac3n,uint64_t SCR,uint32_t muxr,uint8_t * buf)991 int write_nav_pack(int pack_size, int apidn, int ac3n, uint64_t SCR, uint32_t muxr,
992 		   uint8_t *buf)
993 {
994 	int pos = 0;
995         uint8_t headr[5] = {0x00, 0x00, 0x01, PRIVATE_STREAM2, 0x03 };
996 
997 	pos = write_ps_header( buf, SCR, muxr, apidn+ac3n, 0, 0, 1, 1, 1, 1);
998 	memcpy(buf+pos, headr, 5);
999 	buf[pos+5] = 0xD4;
1000 	pos += 6;
1001 	memset(buf+pos, 0, 0x03d4);
1002 	pos += 0x03d4;
1003 
1004 	memcpy(buf+pos, headr, 5);
1005 	buf[pos+5] = 0xFA;
1006 	pos += 6;
1007 	memset(buf+pos, 0, 0x03fA);
1008 	pos += 0x03fA;
1009 
1010 	return pos;
1011 }
1012