Commit files by Steinar Gunderson, forgotten in r30866.
[mplayer/glamo.git] / libmpdemux / mpeg_packetizer.c
blob0b4b1fa8d50f202dfca440242b2f291f890b9571
1 /*
2 * set of helper routines for building MPEG 1/2 PS/PES packets
4 * Copyright (C) 2006 Benjamin Zores
6 * Based on code borrowed from vo_mpegpes/vo_dxr2:
7 * (C) 2000 Ralph Metzler <ralph@convergence.de>
8 * Marcus Metzler <marcus@convergence.de>
9 * Gerard Lantau
11 * This file is part of MPlayer.
13 * MPlayer is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * MPlayer is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <unistd.h>
29 #include <string.h>
30 #include <inttypes.h>
32 #include "mp_msg.h"
33 #include "mpeg_packetizer.h"
35 #define PES_MAX_SIZE 2048
37 static const unsigned char ps2_header[] = {
38 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x04, 0x00,
39 0x04, 0x01, 0x01, 0x86, 0xa3, 0xf8
43 static const unsigned char ps1_header[] = {
44 0x00, 0x00, 0x01, 0xba, 0x21, 0x00,
45 0xb9, 0x37, 0x83, 0x80, 0xc3, 0x51,
48 /* Send MPEG <type> PES packet */
49 static int
50 send_mpeg_pes_packet_ll(unsigned char *data, int len, int id, uint64_t pts,
51 int type, unsigned char *header, int header_len,
52 int align4, int my_write (const unsigned char *data, int len))
54 int ptslen = (pts ? 5 : 0);
55 int n = 0;
56 int idx, plen;
57 int hdr;
58 unsigned char pes_header[PES_MAX_SIZE];
60 mp_msg (MSGT_HEADER, MSGL_DBG2,
61 "MPEG%d PES packet: 0x%x => %"PRIu64" \n", type, id, pts);
62 memset (pes_header, '\0', PES_MAX_SIZE);
64 /* startcode */
65 pes_header[0] = 0;
66 pes_header[1] = 0;
67 pes_header[2] = 0x01;
68 pes_header[3] = id; /* stream id */
70 while (len > 0)
72 int payload_size = len; /* data + PTS */
73 if(type == 2)
74 hdr = 3;
75 else
76 hdr = (ptslen ? 0 : 1);
77 if (6 + hdr + ptslen + payload_size + header_len > PES_MAX_SIZE)
78 payload_size = PES_MAX_SIZE - 6 - hdr - ptslen - header_len;
79 if(align4)
80 payload_size &= ~3;
82 /* construct PES header: packetize */
83 plen = payload_size + hdr + ptslen + header_len;
84 pes_header[4] = plen >> 8;
85 pes_header[5] = plen & 255;
86 idx = 6;
88 if (ptslen)
90 int x;
92 if(type == 2)
94 pes_header[idx++] = 0x81;
95 pes_header[idx++] = 0x80;
96 pes_header[idx++] = ptslen;
99 /* presentation time stamp */
100 x = (0x02 << 4) | (((pts >> 30) & 0x07) << 1) | 1;
101 pes_header[idx++] = x;
103 x = ((((pts >> 15) & 0x7fff) << 1) | 1);
104 pes_header[idx++] = x >>8;
105 pes_header[idx++] = x & 255;
107 x = (((pts & 0x7fff) << 1) | 1);
108 pes_header[idx++] = x >> 8;
109 pes_header[idx++] = x & 255;
111 else
113 if(type == 2)
115 pes_header[idx++] = 0x81;
116 pes_header[idx++] = 0x00;
117 pes_header[idx++] = 0x00;
119 else
120 pes_header[idx++] = 0x0f;
123 if(header_len)
125 memcpy(&pes_header[idx], header, header_len);
126 idx += header_len;
129 my_write (pes_header, idx);
130 n = my_write (data, payload_size);
132 len -= n;
133 data += n;
134 ptslen = 0; /* store PTS only once, at first packet! */
135 if(align4 && len < 4)
136 break;
139 return n;
143 send_mpeg_pes_packet (unsigned char *data, int len, int id, uint64_t pts,
144 int type, int my_write (const unsigned char *data, int len))
146 return send_mpeg_pes_packet_ll(data, len, id, pts, type, NULL, 0, 0, my_write);
150 /* Send MPEG <type> PS packet */
152 send_mpeg_ps_packet(unsigned char *data, int len, int id, uint64_t pts, int type,
153 int my_write (const unsigned char *data, int len))
155 if(type == 2)
156 my_write (ps2_header, sizeof (ps2_header));
157 else
158 my_write (ps1_header, sizeof (ps1_header));
159 return send_mpeg_pes_packet (data, len, id, pts, type, my_write);
162 /* Send MPEG 2 LPCM packet */
164 send_mpeg_lpcm_packet(unsigned char* data, int len,
165 int id, uint64_t pts, int freq_id,
166 int my_write (const unsigned char *data, int len))
168 unsigned char header[7] = {0xA0, 0x07, 0x00, 0x04, 0x0C, 1 | (freq_id << 4), 0x80};
169 return send_mpeg_pes_packet_ll(data, len, 0xBD, pts, 2, header, sizeof(header), 1, my_write);