xref: /utopia/UTPA2-700.0.x/modules/mfe/api/mfe/TsMuxer.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 //    Software and any modification/derivatives thereof.
18 //    No right, ownership, or interest to MStar Software and any
19 //    modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 //    supplied together with third party`s software and the use of MStar
23 //    Software may require additional licenses from third parties.
24 //    Therefore, you hereby agree it is your sole responsibility to separately
25 //    obtain any and all third party right and license necessary for your use of
26 //    such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 //    MStar`s confidential information and you agree to keep MStar`s
30 //    confidential information in strictest confidence and not disclose to any
31 //    third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 //    kind. Any warranties are hereby expressly disclaimed by MStar, including
35 //    without limitation, any warranties of merchantability, non-infringement of
36 //    intellectual property rights, fitness for a particular purpose, error free
37 //    and in conformity with any international standard.  You agree to waive any
38 //    claim against MStar for any loss, damage, cost or expense that you may
39 //    incur related to your use of MStar Software.
40 //    In no event shall MStar be liable for any direct, indirect, incidental or
41 //    consequential damages, including without limitation, lost of profit or
42 //    revenues, lost or damage of data, and unauthorized system use.
43 //    You agree that this Section 4 shall still apply without being affected
44 //    even if MStar Software has been modified by MStar in accordance with your
45 //    request or instruction for your use, except otherwise agreed by both
46 //    parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 //    services in relation with MStar Software to you for your use of
50 //    MStar Software in conjunction with your or your customer`s product
51 //    ("Services").
52 //    You understand and agree that, except otherwise agreed by both parties in
53 //    writing, Services are provided on an "AS IS" basis and the warranty
54 //    disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 //    or otherwise:
58 //    (a) conferring any license or right to use MStar name, trademark, service
59 //        mark, symbol or any other identification;
60 //    (b) obligating MStar or any of its affiliates to furnish any person,
61 //        including without limitation, you and your customers, any assistance
62 //        of any kind whatsoever, or any information; or
63 //    (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 //    of Taiwan, R.O.C., excluding its conflict of law rules.
67 //    Any and all dispute arising out hereof or related hereto shall be finally
68 //    settled by arbitration referred to the Chinese Arbitration Association,
69 //    Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 //    Rules of the Association by three (3) arbitrators appointed in accordance
71 //    with the said Rules.
72 //    The place of arbitration shall be in Taipei, Taiwan and the language shall
73 //    be English.
74 //    The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78 ////////////////////////////////////////////////////////////////////////////////
79 //
80 // Copyright (c) 2006-2009 MStar Semiconductor, Inc.
81 // All rights reserved.
82 //
83 // Unless otherwise stipulated in writing, any and all information contained
84 // herein regardless in any format shall remain the sole proprietary of
85 // MStar Semiconductor Inc. and be kept in strict confidence
86 // (�uMStar Confidential Information�v) by the recipient.
87 // Any unauthorized act including without limitation unauthorized disclosure,
88 // copying, use, reproduction, sale, distribution, modification, disassembling,
89 // reverse engineering and compiling of the contents of MStar Confidential
90 // Information is unlawful and strictly prohibited. MStar hereby reserves the
91 // rights to any and all damages, losses, costs and expenses resulting therefrom.
92 //
93 ////////////////////////////////////////////////////////////////////////////////
94 
95 
96 #include <assert.h>
97 #include <string.h>
98 
99 #include "MFE_chip.h"
100 #include "mfe_common.h"
101 #include "mfe_type.h"
102 #include "madp_ms_dprintf.h"
103 
104 #include "MuxCommon.h"
105 #include "TsMuxer.h"
106 #include <pthread.h>
107 #ifdef FILE_TEST
108     #include <stdio.h>
109 #endif
110 
111 #define MAX_VALUE           (1<<30)
112 //#define INVALID_PTS         ((INT64_C)(0x8000000000000000LL))
113 
114 #define TS_SYNCBYTE  0x47
115 #define TS_PACKET_SIZE 188
116 
117 #ifdef TS_192_BYTE
118 	#define TIMECODE_AHEAD			1000
119     #define TIMECODE_CLOCK			90000//27000000
120 #endif
121 
122 #define DEFAULT_SID             0x0001
123 #define DEFAULT_PMT_START_PID   0x0100
124 #define DEFAULT_START_PID       0x0064    // Valid range [0x0010, 0x1FFE]
125 
126 // PAT
127 #define TID_PAT                 0x00        // table_id
128 #define TSID_DEFAULT            0x0001        // transport_stream_id
129 #define PID_PAT                 0x0000
130 
131 // PMT stream_type
132 #define PMT_STREAM_TYPE_13818_2     0x02
133 #define PMT_STREAM_TYPE_11172_3     0x03
134 #define PMT_STREAM_TYPE_14496_2     0x10
135 #define PMT_STREAM_TYPE_14496_10    0x1b
136 #define TID_PMT                        0x02    // table_id
137 
138 // PES related
139 #define DEFAULT_PES_HEADER_FREQ 16
140 #define DEFAULT_PES_PAYLOAD_SIZE ((DEFAULT_PES_HEADER_FREQ - 1) * 184 + 170)
141 #define PES_NO_VIDEO_PAYLOADSIZE    // If defined, PES payload size is filled as 0
142 #define PES_MAX_PAYLOADSIZE  0xFFFF
143 
144 #define PAT_RETRANS_TIME 100
145 
146 #define PCR_TRANSMISSION
147 #define PCR_RETRANS_TIME 20
148 
149 //////////////////////////////////////////////////////////////////////////
150 // MPEG-TS SI info
151 //////////////////////////////////////////////////////////////////////////
152 
153 static const MFE_U32 gCRC32Table[256] = {
154     0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517, 0xB24D861A, 0x0550471E,
155     0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B, 0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38,
156     0x70DB114C, 0xC7C6D048, 0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652,
157     0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D, 0x7A7B9F70, 0xCD665E74,
158     0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095, 0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486,
159     0x585B2BBE, 0xEF46EABA, 0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0,
160     0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3, 0x2220B4CE, 0x953D75CA,
161     0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF, 0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC,
162     0x77708634, 0xC06D4730, 0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A,
163     0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05, 0x7DD00808, 0xCACDC90C,
164     0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475, 0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066,
165     0xBF469F5E, 0x085B5E5A, 0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840,
166     0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB, 0x258B23B6, 0x9296E2B2,
167     0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87, 0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94,
168     0xE71DB4E0, 0x500075E4, 0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE,
169     0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1, 0xEDBD3ADC, 0x5AA0FBD8,
170     0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64, 0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77,
171     0x560D044F, 0xE110C54B, 0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351,
172     0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832, 0x2C769B3F, 0x9B6B5A3B,
173     0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E, 0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D,
174     0x0E562FF1, 0xB94BEEF5, 0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF,
175     0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0, 0x04F6A1CD, 0xB3EB60C9,
176     0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0, 0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3,
177     0xC660369B, 0x717DF79F, 0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185,
178     0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A, 0x2BDD0C47, 0x9CC0CD43,
179     0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176, 0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565,
180     0xE94B9B11, 0x5E565A15, 0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F,
181     0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620, 0xE3EB152D, 0x54F6D429,
182     0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8, 0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB,
183     0xC1CBA1E3, 0x76D660E7, 0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD,
184     0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E, 0xBBB03E93, 0x0CADFF97,
185     0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2, 0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1,
186 };
187 
getCRC(const MFE_U8 * buffer,size_t length)188 MFE_U32 getCRC(const MFE_U8 *buffer, size_t length)
189 {
190     const MFE_U8 *end= buffer+length;
191     MFE_U32 crc = 0xFFFFFFFF;
192     while(buffer<end)
193         crc = (crc >> 8) ^ gCRC32Table[(crc & 0xFF) ^ *buffer++];
194     return crc;
195 }
196 
197 #ifdef TS_192_BYTE
GetTimecode(MediaContext * ctx,int data_len)198 MFE_U32 GetTimecode(MediaContext* ctx, int data_len)
199 {
200 	int mux_rate, increment;
201     MpegTSWrite *ts = (MpegTSWrite*)ctx->muxinfo;
202 
203 	if (ts->waited_datasize<=0 || ts->min_time<=ctx->timestamp+TIMECODE_AHEAD)
204 		mux_rate = ts->mux_rate;
205 	else
206 		mux_rate = ts->waited_datasize * TIMECODE_CLOCK / (int)(ts->min_time - (ctx->timestamp+TIMECODE_AHEAD));
207 	ts->waited_datasize -= data_len;
208 
209 	increment = data_len * TIMECODE_CLOCK / mux_rate - 1;
210 	if (increment<=0) increment = 1;
211 	ctx->timestamp += increment;
212 #if 0
213 	assert(ctx->streams[0]->payload_pts==INVALID_PTS || ctx->timestamp<ctx->streams[0]->payload_pts);
214 	assert(ctx->streams[1]->payload_pts==INVALID_PTS || ctx->timestamp<ctx->streams[1]->payload_pts);
215 #endif
216 	return (MFE_U32)(ctx->timestamp & 0x3FFFFFFF); // % 2^30
217 }
218 #endif
219 
mpegts_write_section(MediaContext * ctx,MpegTSSection * s,int table_id,int id,MFE_U8 * section,MFE_U32 len)220 static void mpegts_write_section(MediaContext* ctx, MpegTSSection *s, int table_id, int id, MFE_U8 *section, MFE_U32 len)
221 {
222     MFE_U8 *q, *buf_ptr;
223     MFE_U32 tot_len, first, b, len1, left, crc;
224     MpegTSWrite *ts = (MpegTSWrite*)ctx->muxinfo;
225     MFE_U8 packet[TS_PACKET_SIZE];
226     OutDataInfo data_info;
227 
228     tot_len = 8 + len + 4;    // 4: CRC bytes
229     assert(tot_len<=1024);
230 
231     // First common 8 bytes
232     q = section;
233     *q++ = table_id;
234     put16_msbf(&q, 0xb000 | (len + 5 + 4)); // header:5 , CRC:4
235     put16_msbf(&q, id);    // transport_stream_id (PAT) or program_number (PMT)
236     *q++ = 0xc1;    // version_number=0, current_next_indicator=1
237     *q++ = 0x0;        // section_number
238     *q++ = 0x0;        // last_section_number
239 
240     // CRC
241     crc = getCRC(section, tot_len - 4);
242     buf_ptr = &section[tot_len-4];
243     put32_lsbf(&buf_ptr, crc);
244 
245     // ts packets
246     buf_ptr = section;
247     while (tot_len > 0) {
248         first = (section == buf_ptr);
249         q = packet;
250         *q++ = TS_SYNCBYTE;
251         b = (s->pid >> 8);
252         if (first)
253             b |= 0x40;    // payload_unit_start_indicator=1
254         *q++ = b;
255         *q++ = s->pid;
256         *q++ = 0x10 | s->cc;    // no scrambling, payload only
257         s->cc = (s->cc + 1) & 0xF;
258         if (first)
259             *q++ = 0x00;    // pointer_field
260         len1 = TS_PACKET_SIZE - (q - packet);
261         if (len1 > tot_len)
262             len1 = tot_len;
263         memcpy(q, buf_ptr, len1);
264         q += len1;
265         // padding bytes
266         left = TS_PACKET_SIZE - (q - packet);
267         if (left > 0)
268             memset(q, 0xFF, left);
269 
270         data_info.header = packet;
271         data_info.size1 = TS_PACKET_SIZE;
272         data_info.data = 0;
273         data_info.size2 = 0;
274         data_info.write_type = 1;
275         data_info.type = INDEX_TYPE_NONE;
276 #ifdef TS_192_BYTE
277         data_info.write_timecode = 1;
278         data_info.timecode = GetTimecode(ctx, 0);
279 #else
280         data_info.write_timecode = 0;
281 #endif
282         data_info.stuffing = 0;
283         data_info.lock_write = 0;
284         data_info.update_count = 0;
285         outbuf_put(ctx->outstream, &data_info);
286 
287         buf_ptr += len1;
288         tot_len -= len1;
289 #ifdef PCR_TRANSMISSION
290         ts->cur_pcr += TS_PACKET_SIZE*8*90000L/ts->mux_rate;
291 #endif
292     }
293 }
294 
295 // Only 1 program
mpegts_write_pat(MediaContext * s)296 static void mpegts_write_pat(MediaContext *s)
297 {
298     MpegTSWrite *ts = (MpegTSWrite*)s->muxinfo;
299     MFE_U8 data[1024], *q, *pat_start;
300 
301     q = pat_start = data+8;
302     put16_msbf(&q, ts->program.prog_num);    // program_number
303     put16_msbf(&q, 0xe000 | ts->program.pmt.pid);    // program_map_PID
304     mpegts_write_section(s, &ts->pat, TID_PAT, ts->tsid, data, q - pat_start);
305 }
306 
mpegts_write_pmt(MediaContext * s,MpegTSProgram * program)307 static void mpegts_write_pmt(MediaContext *s, MpegTSProgram *program)
308 {
309     MFE_U8 data[1024], *q, *pmt_start, *p_es_desc_len, *p_prog_desc_len;
310     int val;
311 	MFE_U32 stream_type=0, i;
312 
313     q = pmt_start = data+8;
314     put16_msbf(&q, 0xE000 | program->pcr_pid);
315 
316     p_prog_desc_len = q;
317     q += 2;
318 
319     // Optional program descriptor goes here
320 
321     val = 0xF000 | (q - p_prog_desc_len - 2);
322     p_prog_desc_len[0] = val >> 8;
323     p_prog_desc_len[1] = val;
324 
325     for (i=0; i<s->stream_count; i++) {
326         StreamContext *st = s->streams[i];
327         switch(st->codec_id) {
328         case CODEC_ID_VIDEO_MPEG4:
329             stream_type = PMT_STREAM_TYPE_14496_2;
330             break;
331         case CODEC_ID_AUDIO_MP2:
332         case CODEC_ID_AUDIO_MP3:
333             stream_type = PMT_STREAM_TYPE_11172_3;
334             break;
335         case CODEC_ID_VIDEO_MPEG2:
336             stream_type = PMT_STREAM_TYPE_13818_2;
337             break;
338         case CODEC_ID_VIDEO_H264:
339             stream_type = PMT_STREAM_TYPE_14496_10;
340             break;
341         case CODEC_ID_NONE:
342             assert(0);
343             //printf("wrong codec in TSMUXER\n");
344             break;
345         }
346         *q++ = stream_type;
347         put16_msbf(&q, 0xE000 | st->pid);
348         p_es_desc_len = q;
349         q += 2;
350 
351         // Optional stream descriptor goes here
352         switch(st->codec_type) {
353         case CODEC_TYPE_AUDIO:
354             break;
355         case CODEC_TYPE_VIDEO:
356             break;
357         }
358 
359         val = 0xF000 | (q - p_es_desc_len - 2);
360         p_es_desc_len[0] = val >> 8;
361         p_es_desc_len[1] = val;
362     }
363     mpegts_write_section(s, &program->pmt, TID_PMT, program->prog_num, data, q - pmt_start);
364 }
365 
resend_PAT_PMT(MediaContext * s)366 static void resend_PAT_PMT(MediaContext *s)
367 {
368     MpegTSWrite *ts = (MpegTSWrite*)s->muxinfo;
369 
370     if (++ts->pat_packet_count == ts->pat_packet_freq) {
371         ts->pat_packet_count = 0;
372         mpegts_write_pat(s);
373         mpegts_write_pmt(s, &ts->program);
374     }
375 }
376 
377 //////////////////////////////////////////////////////////////////////////
378 // MPEG-TS PES packet
379 //////////////////////////////////////////////////////////////////////////
380 
381 // Write 33-bit PTS or DTS
write_ptsdts(MFE_U8 * q,int fourbits,MFE_S64 pts)382 static void write_ptsdts(MFE_U8 *q, int fourbits, MFE_S64 pts)
383 {
384     int val;
385 
386     pts = pts & MFE_INT64_C(0x1FFFFFFFF);	// % 2^33
387 //       pts &= (MFE_S64)(0x1FFFFFFFF);	// % 2^33
388 
389     val = fourbits << 4 | ((((MFE_U32)(pts>>30)) & 0x07) << 1) | 1;
390     *q++ = val;
391     val = ((((MFE_U32)(pts>>15)) & 0x7fff) << 1) | 1;
392     *q++ = val >> 8;
393     *q++ = val;
394     val = (((MFE_U32)(pts&0x7fff)) << 1) | 1;
395     *q++ = val >> 8;
396     *q++ = val;
397 }
398 
399 // The payload must be either:
400 //    one video frame (with headers after the last bytes of the last frame), or
401 //    one audio frame.
402 // If audio stream, index_type must be INDEX_TYPE_NONE.
mpegts_write_pes(MediaContext * s,StreamContext * st,MFE_U32 payload_size,INDEX_TYPE_T index_type,MFE_U8 first,MFE_U8 last)403 static void mpegts_write_pes(MediaContext *s, StreamContext *st, MFE_U32 payload_size, INDEX_TYPE_T index_type, MFE_U8 first, MFE_U8 last)
404 {
405     MpegTSWrite *ts = (MpegTSWrite*)s->muxinfo;
406     MpegTSProgram* program = (MpegTSProgram*)st->program;
407     MFE_U8 *payload = st->payload;
408     MFE_S64 pts = st->payload_pts;
409     MFE_S64 dts = st->payload_dts;
410     MFE_U8 buf[TS_PACKET_SIZE];
411     MFE_U8 *q;
412     int val, is_start, write_pcr, flags;
413     MFE_U32 len, header_len, data_len, stuffing_len;
414     INDEX_TYPE_T type;
415     OutDataInfo data_info;
416 #ifdef PCR_TRANSMISSION
417     MFE_S64 pcr;
418 #endif
419 
420     //assert( !(index_type!=INDEX_TYPE_NONE&&!last) );
421 
422     is_start = first;//1;
423     stuffing_len = 0;
424     if (ts->temp_size>0) {
425         assert(ts->temp_size<=TS_PACKET_SIZE);
426         payload -= ts->temp_size;
427         payload_size += ts->temp_size;
428         memcpy(payload, ts->temp188, ts->temp_size);
429         ts->temp_size = 0;
430     }
431     type = index_type;
432     while (payload_size > 0) {
433         resend_PAT_PMT(s);
434 
435         write_pcr = 0;
436 #ifdef PCR_TRANSMISSION
437         if (st->pid == program->pcr_pid) {
438             program->pcr_packet_count++;
439             if (program->pcr_packet_count>=program->pcr_packet_freq) {
440                 program->pcr_packet_count = 0;
441                 write_pcr = 1;
442             }
443         }
444 #endif
445         // ts packet header: 4 bytes
446         q = buf;
447         *q++ = TS_SYNCBYTE;
448         val = (st->pid >> 8);
449         if (is_start)
450             val |= 0x40;    // payload_unit_start_indicator=1
451         *q++ = (MFE_U8)val;
452         *q++ = (MFE_U8)st->pid;
453         *q++ = (MFE_U8)((write_pcr ? 0x30 : 0x10) | st->cc);    // no scrambling
454         //st->cc = (st->cc + 1) & 0xF;
455 
456         // adaptation_field and/or PES_packet() starts here.
457 #ifdef PCR_TRANSMISSION
458         if (write_pcr) {
459             // add 11, pcr references the last byte of program clock reference base
460             pcr = ts->cur_pcr + (4+7)*8*90000L / ts->mux_rate;
461             if (dts != INVALID_PTS && dts < pcr)
462                 assert(0);
463             *q++ = 7;        // adaptation_field_length
464             *q++ = 0x10;    // Has PCR
465             *q++ = (MFE_U8)(pcr >> 25);
466             *q++ = (MFE_U8)(pcr >> 17);
467             *q++ = (MFE_U8)(pcr >> 9);
468             *q++ = (MFE_U8)(pcr >> 1);
469             *q++ = (MFE_U8)((pcr&1) << 7);
470             *q++ = 0;
471         }
472 #endif
473         // Stuffing bytes by adaptation_field, if necessary.
474         header_len = q-buf;
475         if (is_start) {
476             header_len += 9;
477             if (pts != INVALID_PTS) {
478                 header_len += 5;
479                 if (dts != pts)
480                     header_len += 5;
481             }
482         }
483         data_len = TS_PACKET_SIZE - header_len;
484         if (data_len > payload_size) {
485             stuffing_len = data_len - payload_size;
486             data_len = payload_size;
487             if (buf[3] & 0x20) {
488                 // already has adaptation_field
489                 len = buf[4] + 1;
490                 buf[4] += stuffing_len;    // Update length
491                 memset(q, 0xFF, stuffing_len);
492                 q += stuffing_len;
493             }
494             else {
495                 buf[3] |= 0x20;    // notify existence of adaptation_field
496                 *q++ = stuffing_len-1;    // adaptation_field_length is used for 1-byte stuffing.
497                 if (stuffing_len >= 2) {
498                     *q++ = 0x00;    // All flags are zero.
499                     memset(q, 0xFF, stuffing_len-2);
500                     q += stuffing_len-2;
501                 }
502             }
503         }
504 
505         if (is_start) {
506             // PES header
507             *q++ = 0x00;
508             *q++ = 0x00;
509             *q++ = 0x01;
510             if (st->codec_type == CODEC_TYPE_VIDEO) {
511                 *q++ = 0xe0;    // MPEG-1 or MPEG-2 or MPEG-4 or H.264 video
512             } else if (st->codec_type == CODEC_TYPE_AUDIO &&
513                 (st->codec_id==CODEC_ID_AUDIO_MP2 || st->codec_id==CODEC_ID_AUDIO_MP3)) {
514                 *q++ = 0xc0;
515             }
516             header_len = 0;
517             flags = 0;
518             if (pts != INVALID_PTS) {
519                 header_len += 5;
520                 flags |= 0x80;
521                 if (dts != pts) {
522                     header_len += 5;
523                     flags |= 0x40;
524                 }
525             }
526             len = payload_size + header_len + 3;
527 #ifdef PES_NO_VIDEO_PAYLOADSIZE
528             if (st->codec_type == CODEC_TYPE_VIDEO) {
529                 *q++ = 0;
530                 *q++ = 0;
531             }
532             else
533 #endif
534             {
535                 assert(len<PES_MAX_PAYLOADSIZE);
536                 *q++ = len >> 8;
537                 *q++ = len;
538             }
539             val = 0x80;
540             *q++ = val;
541             *q++ = flags;
542             *q++ = header_len;
543             if (pts != INVALID_PTS) {
544                 write_ptsdts(q, flags >> 6, pts);
545                 q += 5;
546                 if (dts != pts) {
547                     write_ptsdts(q, 1, dts);
548                     q += 5;
549                 }
550             }
551             //is_start = 0;
552         }
553 
554         // pes_packet_data_byte
555         //memcpy(q, payload, data_len);
556         assert(q+data_len-buf==TS_PACKET_SIZE);
557 
558         if (!last && stuffing_len>0) {
559             assert(ts->temp_size==0);
560             memcpy(ts->temp188, payload, payload_size);
561             ts->temp_size = payload_size;
562             break;
563         }
564 
565         data_info.header = buf;
566         data_info.size1 = TS_PACKET_SIZE-data_len;
567         data_info.data = payload;
568         data_info.size2 = data_len;
569         data_info.write_type = 1;
570         data_info.type = (last&&is_start) ? type : INDEX_TYPE_NONE;
571 #ifdef TS_192_BYTE
572         data_info.write_timecode = 1;
573         data_info.timecode = GetTimecode(s, data_len);
574 #else
575         data_info.write_timecode = 0;
576 #endif
577         data_info.stuffing = 0;
578         data_info.lock_write = last ? 0 : 1;
579         data_info.update_count = 0;
580         outbuf_put(s->outstream, &data_info);
581 
582         // Prepare for next round
583         st->cc = (st->cc + 1) & 0xF;
584         payload += data_len;
585         payload_size -= data_len;
586         if (is_start) {
587             is_start = 0;
588             type = INDEX_TYPE_NONE;
589         }
590 #ifdef PCR_TRANSMISSION
591         ts->cur_pcr += TS_PACKET_SIZE*8*90000L/ts->mux_rate;
592 #endif
593     }
594 }
595 
596 //////////////////////////////////////////////////////////////////////////
597 // TS-mux external API's
598 //////////////////////////////////////////////////////////////////////////
599 
tsmux_open(struct avmux_s * inst)600 int tsmux_open(struct avmux_s *inst)
601 {
602     MediaContext *s = inst->mctx;
603     MpegTSWrite *ctx = (MpegTSWrite*)s->muxinfo;
604     MpegTSProgram *program = &ctx->program;
605     StreamContext *st;
606     MFE_U32 i, total_bit_rate;
607     MFE_U32 pat_pmt_size;
608     MFE_U64 pos;
609 
610 #ifdef TS_192_BYTE
611     s->timestamp = 0;
612 #endif
613 
614     outbuf_init(s->outstream);
615 
616     ctx->tsid = TSID_DEFAULT;
617     ctx->pat.pid = PID_PAT;
618     ctx->pat.cc = 0;
619     ctx->pat_packet_count = 0;
620     ctx->cur_pcr = 0;
621     ctx->temp_size = 0;
622 	ctx->min_time = 0;
623 	ctx->waited_datasize = 0;
624 
625     /* Initial the single program */
626     program->pmt.pid = DEFAULT_PMT_START_PID;
627     program->pmt.cc =0;
628     program->prog_num = DEFAULT_SID;
629     program->pcr_pid = 0x1FFF;
630     program->pcr_packet_count = 0;
631 
632     // Initial streams
633     total_bit_rate = 0;
634     for(i=0; i<s->stream_count; i++) {
635         st = s->streams[i];
636         st->cc = 0;
637         st->program = program;
638         if (st->pid==0)    // If not forced.
639             st->pid = DEFAULT_START_PID + i;
640         st->payload_pts = INVALID_PTS;
641         st->payload_dts = INVALID_PTS;
642         // PCR pid is the first video stream
643         if (st->codec_type == CODEC_TYPE_VIDEO && program->pcr_pid == 0x1FFF)
644             program->pcr_pid = st->pid;
645         total_bit_rate += st->bit_rate;
646     }
647 
648     // if no video stream, use the first stream as PCR
649     if (program->pcr_pid == 0x1FFF && s->stream_count > 0) {
650         program->pcr_pid = s->streams[0]->pid;
651     }
652 
653     if (total_bit_rate <= 8 * 1024)
654         total_bit_rate = 8 * 1024;
655     program->pcr_packet_freq = MAX_VALUE;//(total_bit_rate * PCR_RETRANS_TIME) / (TS_PACKET_SIZE * 8 * 1000);
656     ctx->pat_packet_freq = MAX_VALUE;//(total_bit_rate * PAT_RETRANS_TIME) / (TS_PACKET_SIZE * 8 * 1000);
657 
658     ctx->mux_rate = 1+total_bit_rate;
659     pos = s->outstream->total_size;
660     mpegts_write_pat(s);
661     mpegts_write_pmt(s, &ctx->program);
662     pat_pmt_size = (MFE_U32)(s->outstream->total_size - pos);
663 
664     total_bit_rate +=
665         total_bit_rate * 25 / (8 * DEFAULT_PES_PAYLOAD_SIZE) // PES header
666         + total_bit_rate * 4 / (8 * TS_PACKET_SIZE)          // TS header
667         + PAT_RETRANS_TIME * pat_pmt_size                     // PAT+PMT size
668 #ifdef PCR_TRANSMISSION
669         + PCR_RETRANS_TIME * 8                              // PCR size
670 #endif
671         ;
672     ctx->mux_rate = total_bit_rate;
673 
674 #ifdef PCR_TRANSMISSION
675     ctx->cur_pcr /= ctx->mux_rate;
676 #endif
677 
678     return 0;
679 }
680 
tsmux_write_packet(struct avmux_s * inst,AUContext * pkt)681 int tsmux_write_packet(struct avmux_s *inst, AUContext *pkt)
682 {
683     MediaContext *s = inst->mctx;
684 #ifdef TS_192_BYTE
685     MpegTSWrite *ts = (MpegTSWrite*)s->muxinfo;
686     int i;
687     MFE_S64 min_ts;
688 #endif
689     StreamContext *st = s->streams[pkt->stream_index];
690     MFE_U8 *buf= pkt->access_unit;
691     //const MFE_U8 *access_unit_index = NULL;
692     MFE_S64 dts = INVALID_PTS, pts = INVALID_PTS;
693 
694     //assert(pkt->first_segment==1 && pkt->last_segment==1);
695     if (pkt->pts != INVALID_PTS)
696         pts = pkt->pts;
697     if (pkt->dts != INVALID_PTS)
698         dts = pkt->dts;
699 
700     st->payload = buf;
701     st->payload_dts = dts;
702     st->payload_pts = pts;
703 
704 #ifdef TS_192_BYTE
705     if (pkt->first_segment) {
706         assert(pts!=INVALID_PTS);
707 		min_ts = s->streams[0]->payload_pts==INVALID_PTS ? 0 :  s->streams[0]->payload_pts;
708 		for (i=1; i<(int)s->stream_count; i++) {
709             if (s->streams[i]->payload_pts==INVALID_PTS)
710                 min_ts = 0;
711             else if (s->streams[i]->payload_pts<min_ts)
712                 min_ts = s->streams[i]->payload_pts;
713         }
714 		ts->min_time = min_ts;
715     }
716 	ts->waited_datasize += pkt->unit_size;
717 #endif
718 
719 	mpegts_write_pes(s, st, pkt->unit_size, pkt->index_type, pkt->first_segment, pkt->last_segment);
720     return 0;
721 }
722 
tsmux_close(struct avmux_s * inst)723 int tsmux_close(struct avmux_s *inst)
724 {
725     MediaContext *s = inst->mctx;
726     outbuf_flush(s->outstream);
727     outbuf_close(s->outstream);
728     return 0;
729 }
730