1 /*
2  * PES elementary stream functions
3  * Copyright (C) 2010-2011 Unix Solutions Ltd.
4  *
5  * Released under MIT license.
6  * See LICENSE-MIT.txt for license terms.
7  */
8 #include <netdb.h>
9 #include <string.h>
10 
11 #include "tsfuncs.h"
12 
ts_pes_es_mpeg_audio_header_parse(struct mpeg_audio_header * mpghdr,uint8_t * data,int datasz)13 int ts_pes_es_mpeg_audio_header_parse(struct mpeg_audio_header *mpghdr, uint8_t *data, int datasz) {
14 	if (datasz < 4)
15 		return 0;
16 
17 	uint8_t d1 = data[0];
18 	uint8_t d2 = data[1];
19 	uint8_t d3 = data[2];
20 	uint8_t d4 = data[3];
21 
22 	mpghdr->syncword		= (int)d1 << 4 | (d2 >> 4);			// 12 bits
23 	mpghdr->ID				= bit_on(d2, bit_4);				// 1 bit
24 	mpghdr->layer			= (d2 &~ 0xf9) >> 1;				// 2 bits
25 	mpghdr->protection_bit	= bit_on(d2, bit_1);				// 1 bit
26 
27 	mpghdr->bitrate_index	= d3 >> 4;							// 4 bits
28 	mpghdr->sampl_freq		= (d3 &~ 0xf3) >> 2;				// 2 bits
29 	mpghdr->padding_bit		= bit_on(d3, bit_2);				// 1 bit
30 	mpghdr->private_bit		= bit_on(d3, bit_1);				// 1 bit
31 
32 	mpghdr->mode			= d4 >> 6;							// 2 bits
33 	mpghdr->mode_extension	= (d4 &~ 0xcf) >> 4;				// 2 bits
34 	mpghdr->copyright		= bit_on(d4, bit_4);				// 1 bit
35 	mpghdr->org_home		= bit_on(d4, bit_3);				// 1 bit
36 	mpghdr->emphasis		= d4 &~ 0xfc;						// 2 bits
37 
38 	if (mpghdr->syncword != 0xfff) {
39 		ts_LOGf("!!! Error parsing mpeg audio header! Syncword should be 0xfff but it is 0x%03x!\n", mpghdr->syncword);
40 		return 0;
41 	} else {
42 		mpghdr->initialized = 1;
43 		return 1;
44 	}
45 }
46 
ts_pes_es_mpeg_audio_header_dump(struct mpeg_audio_header * mpghdr)47 void ts_pes_es_mpeg_audio_header_dump(struct mpeg_audio_header *mpghdr) {
48 	if (!mpghdr->initialized)
49 		return;
50 	// See ISO-11172-3 for more info
51 	ts_LOGf("  - ES analyze audio frame\n");
52 	ts_LOGf("    - Syncword      : %x\n", mpghdr->syncword);
53 	if (mpghdr->syncword != 0xfff) {
54 		ts_LOGf("!!! ERROR: MPEG audo Syncword should be 0xfff!\n");
55 		return;
56 	}
57 	ts_LOGf("    - ID            : %d (%s)\n", mpghdr->ID, mpghdr->ID ? "MPEG Audio" : "Other");
58 	ts_LOGf("    - layer         : %d (%s)\n", mpghdr->layer,
59 		mpghdr->layer == 0 ? "reserved" :
60 		mpghdr->layer == 1 ? "Layer III" :
61 		mpghdr->layer == 2 ? "Layer II" :
62 		mpghdr->layer == 3 ? "Layer I" : "reserved"
63 	);
64 	ts_LOGf("    - protection_bit: %x\n", mpghdr->protection_bit);
65 	int br = 0;
66 	if (mpghdr->layer > 0 && mpghdr->layer < 4) {
67 		int bitrate_index_table[4][16] = {
68 			[3] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1},	// Layer 1
69 			[2] = { 0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, -1},	// Layer 2
70 			[1] = { 0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, -1}	// Layer 3
71 		};
72 		br = bitrate_index_table[mpghdr->layer][mpghdr->bitrate_index];
73 	}
74 	ts_LOGf("    - bitrate_index : %d (%d kBit/s)\n", mpghdr->bitrate_index, br);
75 	ts_LOGf("    - sampl_freq    : %d (%s)\n", mpghdr->sampl_freq,
76 		mpghdr->sampl_freq == 0 ? "44.1 kHz" :
77 		mpghdr->sampl_freq == 1 ? "48 kHz" :
78 		mpghdr->sampl_freq == 2 ? "32 kHz" : "reserved"
79 	);
80 	ts_LOGf("    - padding_bit   : %d\n", mpghdr->padding_bit);
81 	ts_LOGf("    - private_bit   : %d\n", mpghdr->private_bit);
82 	ts_LOGf("    - mode          : %d (%s)\n", mpghdr->mode,
83 		mpghdr->mode == 0 ? "stereo" :
84 		mpghdr->mode == 1 ? "join_stereo" :
85 		mpghdr->mode == 2 ? "dual_channel" : "single_channel"
86 	);
87 	ts_LOGf("    - mode_extension: %x\n", mpghdr->mode_extension);
88 	ts_LOGf("    - copyright     : %x\n", mpghdr->copyright);
89 	ts_LOGf("    - org_home      : %x\n", mpghdr->org_home);
90 	ts_LOGf("    - emphasis      : %d (%s)\n", mpghdr->emphasis,
91 		mpghdr->emphasis == 0 ? "none" :
92 		mpghdr->emphasis == 1 ? "50/15 microseconds" :
93 		mpghdr->emphasis == 2 ? "reserved" : "CCITT J.17"
94 	);
95 }
96 
ts_pes_es_parse(struct ts_pes * pes)97 void ts_pes_es_parse(struct ts_pes *pes) {
98 	if (!pes->es_data)
99 		return;
100 
101 	// Parse MPEG audio packet header
102 	if ((pes->is_audio_mpeg1 || pes->is_audio_mpeg2) && pes->es_data_size > 4) {
103 		struct mpeg_audio_header mpghdr;
104 		memset(&mpghdr, 0, sizeof(struct mpeg_audio_header));
105 		ts_pes_es_mpeg_audio_header_parse(&mpghdr, pes->es_data, pes->es_data_size);
106 		if (mpghdr.initialized) {
107 			pes->mpeg_audio_header = mpghdr;
108 			if (mpghdr.ID) {
109 				switch (mpghdr.layer) {
110 					case 3: pes->is_audio_mpeg1l1 = 1; break;
111 					case 2: pes->is_audio_mpeg1l2 = 1; break;
112 					case 1: pes->is_audio_mpeg1l3 = 1; break;
113 				}
114 			}
115 		}
116 	}
117 
118 	// Look into elementary streams to detect AC3/DTS
119 	if (pes->is_audio_ac3) {
120 		if (pes->real_pes_packet_len >= 2 && (pes->es_data[0] == 0x0B && pes->es_data[1] == 0x77)) {
121 			pes->is_audio     = 1;
122 			pes->is_audio_ac3 = 1;
123 			pes->is_audio_dts = 0;
124 		}
125 		if (pes->real_pes_packet_len >= 4 && (pes->es_data[0] == 0x7f && pes->es_data[1] == 0xfe && pes->es_data[2] == 0x80 && pes->es_data[3] == 0x01)) {
126 			pes->is_audio     = 1;
127 			pes->is_audio_ac3 = 0;
128 			pes->is_audio_dts = 1;
129 		}
130 	}
131 }
132 
ts_pes_es_dump(struct ts_pes * pes)133 void ts_pes_es_dump(struct ts_pes *pes) {
134 	if (pes->is_audio && pes->mpeg_audio_header.initialized) {
135 		ts_pes_es_mpeg_audio_header_dump(&pes->mpeg_audio_header);
136 	}
137 }
138