Initial revision
[libav.git] / mpegmux.c
CommitLineData
9aeeeb63
FB
1/*
2 * Output a MPEG1 multiplexed video/audio stream
3 * Copyright (c) 2000 Gerard Lantau.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <netinet/in.h>
23#include <linux/videodev.h>
24#include <unistd.h>
25#include <fcntl.h>
26#include <sys/ioctl.h>
27#include <sys/mman.h>
28#include <errno.h>
29#include <sys/time.h>
30#include <getopt.h>
31
32#include "mpegenc.h"
33#include "mpegvideo.h"
34#include "mpegaudio.h"
35
36#define MAX_PAYLOAD_SIZE 4096
37#define NB_STREAMS 2
38
39typedef struct {
40 UINT8 buffer[MAX_PAYLOAD_SIZE];
41 int buffer_ptr;
42 UINT8 id;
43 int max_buffer_size;
44 int packet_number;
45 AVEncodeContext *enc;
46 float pts;
47} StreamInfo;
48
49typedef struct {
50 int packet_size; /* required packet size */
51 int packet_number;
52 int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */
53 int system_header_freq;
54 int mux_rate; /* bitrate in units of 50 bytes/s */
55 /* stream info */
56 int nb_streams;
57 StreamInfo streams[NB_STREAMS];
58 AVFormatContext *ctx;
59} MpegMuxContext;
60
61#define PACK_START_CODE ((unsigned int)0x000001ba)
62#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
63#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00)
64#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)
65#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
66
67#define AUDIO_ID 0xc0
68#define VIDEO_ID 0xe0
69
70static int put_pack_header(MpegMuxContext *s, UINT8 *buf, long long timestamp)
71{
72 PutBitContext pb;
73
74 init_put_bits(&pb, buf, 128, NULL, NULL);
75
76 put_bits(&pb, 32, PACK_START_CODE);
77 put_bits(&pb, 4, 0x2);
78 put_bits(&pb, 3, (timestamp >> 30) & 0x07);
79 put_bits(&pb, 1, 1);
80 put_bits(&pb, 15, (timestamp >> 15) & 0x7fff);
81 put_bits(&pb, 1, 1);
82 put_bits(&pb, 15, (timestamp) & 0x7fff);
83 put_bits(&pb, 1, 1);
84 put_bits(&pb, 1, 1);
85 put_bits(&pb, 22, s->mux_rate);
86
87 flush_put_bits(&pb);
88 return pb.buf_ptr - pb.buf;
89}
90
91static int put_system_header(MpegMuxContext *s, UINT8 *buf)
92{
93 int audio_bound, video_bound;
94 int size, rate_bound, i;
95 PutBitContext pb;
96
97 init_put_bits(&pb, buf, 128, NULL, NULL);
98
99 put_bits(&pb, 32, SYSTEM_HEADER_START_CODE);
100 put_bits(&pb, 16, 0);
101 put_bits(&pb, 1, 1);
102
103 rate_bound = s->mux_rate; /* maximum bit rate of the multiplexed stream */
104 put_bits(&pb, 22, rate_bound);
105 put_bits(&pb, 1, 1); /* marker */
106 audio_bound = 1; /* at most one audio stream */
107 put_bits(&pb, 6, audio_bound);
108
109 put_bits(&pb, 1, 0); /* variable bitrate */
110 put_bits(&pb, 1, 0); /* non constrainted bit stream */
111
112 put_bits(&pb, 1, 1); /* audio locked */
113 put_bits(&pb, 1, 1); /* video locked */
114 put_bits(&pb, 1, 1); /* marker */
115
116 video_bound = 1; /* at most one video stream */
117 put_bits(&pb, 5, video_bound);
118 put_bits(&pb, 8, 0xff); /* reserved byte */
119
120 /* audio stream info */
121 for(i=0;i<s->nb_streams;i++) {
122 put_bits(&pb, 8, s->streams[i].id); /* stream ID */
123 put_bits(&pb, 2, 3);
124 put_bits(&pb, 1, 1); /* buffer bound scale = 1024 */
125 put_bits(&pb, 13, s->streams[i].max_buffer_size); /* max buffer size */
126 }
127 /* no more streams */
128 put_bits(&pb, 1, 0);
129 flush_put_bits(&pb);
130 size = pb.buf_ptr - pb.buf;
131 /* patch packet size */
132 buf[4] = (size - 6) >> 8;
133 buf[5] = (size - 6) & 0xff;
134
135 return size;
136}
137
138/* Format a packet header for a total size of 'total_size'. Return the
139 header size */
140static int put_packet_header(MpegMuxContext *s,
141 int id, long long timestamp,
142 UINT8 *buffer, int total_size)
143{
144 UINT8 *buf_ptr;
145 PutBitContext pb;
146 int size, payload_size;
147
148#if 0
149 printf("packet ID=%2x PTS=%0.3f size=%d\n",
150 id, timestamp / 90000.0, total_size);
151#endif
152
153 buf_ptr = buffer;
154
155 if ((s->packet_number % s->pack_header_freq) == 0) {
156 /* output pack and systems header */
157 size = put_pack_header(s, buf_ptr, timestamp);
158 buf_ptr += size;
159 if ((s->packet_number % s->system_header_freq) == 0) {
160 size = put_system_header(s, buf_ptr);
161 buf_ptr += size;
162 }
163 }
164
165 payload_size = total_size - ((buf_ptr - buffer) + 6 + 5);
166 /* packet header */
167 init_put_bits(&pb, buf_ptr, 128, NULL, NULL);
168
169 put_bits(&pb, 32, PACKET_START_CODE_PREFIX + id);
170 put_bits(&pb, 16, payload_size + 5);
171 /* presentation time stamp */
172 put_bits(&pb, 4, 0x02);
173 put_bits(&pb, 3, (timestamp >> 30) & 0x07);
174 put_bits(&pb, 1, 1);
175 put_bits(&pb, 15, (timestamp >> 15) & 0x7fff);
176 put_bits(&pb, 1, 1);
177 put_bits(&pb, 15, (timestamp) & 0x7fff);
178 put_bits(&pb, 1, 1);
179
180 flush_put_bits(&pb);
181
182 s->packet_number++;
183 return pb.buf_ptr - buffer;
184}
185
186int mpeg_mux_init(AVFormatContext *ctx)
187{
188 MpegMuxContext *s;
189 int bitrate, i;
190
191 s = malloc(sizeof(MpegMuxContext));
192 if (!s)
193 return -1;
194 memset(s, 0, sizeof(MpegMuxContext));
195 ctx->priv_data = s;
196 s->ctx = ctx;
197 s->packet_number = 0;
198
199 /* XXX: hardcoded */
200 s->packet_size = 2048;
201 s->nb_streams = 2;
202 s->streams[0].id = AUDIO_ID;
203 s->streams[0].max_buffer_size = 10; /* in KBytes */
204 s->streams[0].enc = ctx->audio_enc;
205 s->streams[1].id = VIDEO_ID;
206 s->streams[1].max_buffer_size = 50; /* in KBytes */
207 s->streams[1].enc = ctx->video_enc;
208
209 /* we increase slightly the bitrate to take into account the
210 headers. XXX: compute it exactly */
211 bitrate = 2000;
212 for(i=0;i<s->nb_streams;i++) {
213 bitrate += s->streams[i].enc->bit_rate;
214 }
215 s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);
216 /* every 2 seconds */
217 s->pack_header_freq = 2 * bitrate / s->packet_size / 8;
218 /* every 10 seconds */
219 s->system_header_freq = s->pack_header_freq * 5;
220
221 for(i=0;i<NB_STREAMS;i++) {
222 s->streams[i].buffer_ptr = 0;
223 s->streams[i].packet_number = 0;
224 s->streams[i].pts = 0;
225 }
226 return 0;
227}
228
229int mpeg_mux_end(AVFormatContext *ctx)
230{
231 PutBitContext pb;
232 UINT8 buffer[128];
233
234 /* write the end header */
235 init_put_bits(&pb, buffer, sizeof(buffer), NULL, NULL);
236 put_bits(&pb, 32, ISO_11172_END_CODE);
237
238 put_buffer(&ctx->pb, buffer, pb.buf_ptr - buffer);
239 put_flush_packet(&ctx->pb);
240 return 0;
241}
242
243static void write_stream(MpegMuxContext *s, StreamInfo *stream, UINT8 *buf, int size)
244{
245 int len, len1, header_size;
246 long long pts;
247 while (size > 0) {
248 if (stream->buffer_ptr == 0) {
249 pts = stream->pts * 90000.0;
250 header_size = put_packet_header(s, stream->id, pts, stream->buffer, s->packet_size);
251 stream->buffer_ptr = header_size;
252 }
253 len = size;
254 len1 = s->packet_size - stream->buffer_ptr;
255 if (len > len1)
256 len = len1;
257 memcpy(stream->buffer + stream->buffer_ptr, buf, len);
258 stream->buffer_ptr += len;
259 if (stream->buffer_ptr == s->packet_size) {
260 /* output the packet */
261 put_buffer(&s->ctx->pb, stream->buffer, s->packet_size);
262 put_flush_packet(&s->ctx->pb);
263 stream->buffer_ptr = 0;
264 stream->packet_number++;
265 }
266 buf += len;
267 size -= len;
268 }
269}
270
271static int mpeg_mux_write_audio(AVFormatContext *ctx, UINT8 *buf, int size)
272{
273 MpegMuxContext *s = ctx->priv_data;
274
275 write_stream(s, &s->streams[0], buf, size);
276 s->streams[0].pts += (float)s->streams[0].enc->frame_size / s->streams[0].enc->rate;
277 return 0;
278}
279
280int mpeg_mux_write_video(AVFormatContext *ctx, UINT8 *buf, int size)
281{
282 MpegMuxContext *s = ctx->priv_data;
283
284 write_stream(s, &s->streams[1], buf, size);
285 s->streams[1].pts += 1.0 / (float)s->streams[1].enc->rate;
286
287 return 0;
288}
289
290AVFormat mpeg_mux_format = {
291 "mpeg1",
292 "MPEG1 multiplex format",
293 "video/mpeg",
294 "mpg,mpeg",
295 CODEC_ID_MP2,
296 CODEC_ID_MPEG1VIDEO,
297 mpeg_mux_init,
298 mpeg_mux_write_audio,
299 mpeg_mux_write_video,
300 mpeg_mux_end,
301};