7 #define PACKET_SIZE 2048
12 unsigned char packet_buffer[PACKET_SIZE];
18 void *operator new(size_t n) {
19 void *t = (void*) new char[n];
23 void operator delete(void *t,size_t n) {
35 int write_pack_header(unsigned char *ptr,
48 if(mplex->derivative == 1)
50 unsigned long timestamp = (unsigned long)(seconds * 90000);
52 *ptr++ |= ((timestamp & 0xc0000000) >> 29) | 1;
53 *ptr++ = (timestamp & 0x3fc00000) >> 22;
54 *ptr++ = ((timestamp & 0x003f8000) >> 14) | 1;
55 *ptr++ = (timestamp & 0x00007f80) >> 7;
56 *ptr++ = ((timestamp & 0x0000007f) << 1) | 1;
63 if(mplex->derivative == 2)
77 packet_length = PACKET_SIZE - (ptr - mplex->packet_buffer) - 2;
78 *ptr++ = (packet_length & 0xff00) >> 8;
79 *ptr++ = packet_length & 0xff;
93 return PACKET_SIZE - (ptr - mplex->packet_buffer);
96 int write_packet(track_t *track,
105 long bytes_needed = track->bytes_decoded - ftell(track->raw_file);
106 long current_byte = 0;
108 while(current_byte < bytes_needed)
110 // Write packet header
111 float current_time = start_time + (float)current_byte / bytes_needed * (end_time - start_time);
112 int packet_bytes = write_pack_header(mplex->packet_buffer,
117 unsigned char *ptr = mplex->packet_buffer + PACKET_SIZE - packet_bytes;
118 /*int bytes_read =*/ fread(ptr, 1, packet_bytes, track->raw_file);
120 result = !fwrite(mplex->packet_buffer, PACKET_SIZE, 1, mplex->out_file);
121 current_byte += packet_bytes;
126 int main(int argc, char *argv[])
131 track_t *atracks[streams + 1];
132 track_t *vtracks[streams + 1];
133 int total_atracks = 0;
134 int total_vtracks = 0;
135 float frame_rate = 30000.0 / 1001.0;
136 float sample_rate = 48000;
137 long frames_decoded = 0;
138 float *audio_temp = new float[1];
139 long audio_temp_allocated = 0;
140 float current_time = 0, previous_time = 0;
141 int video_completed = 0;
142 int audio_completed = 0;
147 char *output_path = 0;
148 int old_percentage = 0;
150 path = new char*[argc];
151 mplex.derivative = 1;
156 printf("Tiny MPLEX by Heroine Virtual Ltd.\n");
157 printf("Usage: mplex [-a] <stream 1> <stream2> ... <output>\n");
158 printf(" -a use ac3 packet headers\n");
162 for(i = 1; i < argc; i++)
164 if(!strcmp(argv[i], "-a"))
171 output_path = argv[i];
175 path[stream] = new char[strlen(argv[i])+1];
176 strcpy(path[stream], argv[i]);
183 for(stream = 0; stream < streams; stream++)
185 int is_audio, is_video;
187 mpeg3_t *file = mpeg3_open(path[stream], &error_return);
191 printf("Couldn't open %s\n", path[stream]);
196 is_audio = mpeg3_has_audio(file);
197 is_video = mpeg3_has_video(file);
198 mpeg3_set_cpus(file, 2);
200 if(is_audio && is_video)
202 printf("%s: Can't multiplex a system stream.\n", path[stream]);
208 atracks[total_atracks] = new track_t();
209 atracks[total_atracks]->file = file;
210 sample_rate = mpeg3_sample_rate(file, 0);
211 atracks[total_atracks]->raw_file = fopen(path[stream], "rb");
212 atracks[total_atracks]->stream_number = total_atracks;
218 vtracks[total_vtracks] = new track_t();
219 vtracks[total_vtracks]->file = file;
220 frame_rate = mpeg3_frame_rate(file, 0);
221 vtracks[total_vtracks]->raw_file = fopen(path[stream], "rb");
222 vtracks[total_vtracks]->stream_number = total_vtracks;
223 // Get the first frame
224 mpeg3_skip_video_frame(vtracks[total_vtracks]->file,0);
229 printf("%s: Has neither audio or video.\n", path[stream]);
239 printf("You must supply at least 1 video track.\n");
246 if(!(mplex.out_file = fopen(output_path, "wb")))
248 printf("Couldn't open output file\n");
252 // Write multiplexed stream
255 while(!result && !(video_completed && audio_completed))
257 previous_time = current_time;
258 // Want the frame to come before the audio that goes with it.
259 for(stream = 0; stream < total_vtracks && !result; stream++)
261 // Decode a frame and write it
262 track_t *track = vtracks[stream];
264 if(!track->end_of_data)
267 mpeg3_skip_video_frame(track->file,0);
268 track->frames_decoded++;
269 track->bytes_decoded = mpeg3_video_tell_byte(track->file,0);
270 if(track->frames_decoded > frames_decoded)
272 frames_decoded = track->frames_decoded;
273 current_time = (float)frames_decoded / frame_rate;
276 result = write_packet(track,
280 0xe0 | track->stream_number,
282 track->end_of_data = mpeg3_end_of_video(track->file, 0);
283 percentage = (int)(mpeg3_video_tell_byte(track->file,0) * 100 /
284 mpeg3_get_bytes(track->file));
285 if(percentage - old_percentage >= 1)
287 printf("\t%d%% completed\r", percentage);
288 old_percentage = percentage;
294 // Decode audio until the last frame is covered
295 for(stream = 0; stream < total_atracks && !result; stream++)
297 track_t *track = atracks[stream];
298 //printf("mplex decode audio 1\n");
299 if(!track->end_of_data &&
300 (track->samples_decoded < current_time * sample_rate ||
305 long samples_needed = (long)(current_time * sample_rate) - track->samples_decoded;
306 if(audio_temp_allocated < samples_needed)
308 delete [] audio_temp;
309 audio_temp = new float[samples_needed];
310 audio_temp_allocated = samples_needed;
313 mpeg3_read_audio(track->file,
319 track->bytes_decoded = mpeg3_audio_tell_byte(track->file,0);
320 if(!track->end_of_data) track->bytes_decoded -= 2048;
321 track->samples_decoded += samples_needed;
322 track->end_of_data = mpeg3_end_of_audio(track->file, 0);
326 track->bytes_decoded = mpeg3_get_bytes(track->file);
327 track->end_of_data = 1;
330 //printf("mplex decode audio 2\n");
331 result = write_packet(track,
335 ac3 ? track->stream_number : (0xc0 | track->stream_number),
340 for(stream = 0; stream < total_vtracks; stream++)
342 if(vtracks[stream]->end_of_data) video_completed++;
344 if(video_completed < total_vtracks) video_completed = 0;
346 for(stream = 0; stream < total_atracks; stream++)
348 if(atracks[stream]->end_of_data) audio_completed++;
350 if(audio_completed < total_atracks) audio_completed = 0;
355 for(stream = 0; stream < total_atracks; stream++)
357 mpeg3_close(atracks[stream]->file);
358 fclose(atracks[stream]->raw_file);
359 delete atracks[stream];
362 for(stream = 0; stream < total_vtracks; stream++)
364 mpeg3_close(vtracks[stream]->file);
365 fclose(vtracks[stream]->raw_file);
366 delete vtracks[stream];
369 if(mplex.out_file) fclose(mplex.out_file);