6 #include "mpeg3protos.h"
8 #define PACKET_SIZE 2048
13 unsigned char packet_buffer
[PACKET_SIZE
];
28 int write_pack_header(unsigned char *ptr
,
41 if(mplex
->derivative
== 1)
43 unsigned long timestamp
= (unsigned long)(seconds
* 90000);
45 *ptr
++ |= ((timestamp
& 0xc0000000) >> 29) | 1;
46 *ptr
++ = (timestamp
& 0x3fc00000) >> 22;
47 *ptr
++ = ((timestamp
& 0x003f8000) >> 14) | 1;
48 *ptr
++ = (timestamp
& 0x00007f80) >> 7;
49 *ptr
++ = ((timestamp
& 0x0000007f) << 1) | 1;
56 if(mplex
->derivative
== 2)
70 packet_length
= PACKET_SIZE
- (ptr
- mplex
->packet_buffer
) - 2;
71 *ptr
++ = (packet_length
& 0xff00) >> 8;
72 *ptr
++ = packet_length
& 0xff;
86 return PACKET_SIZE
- (ptr
- mplex
->packet_buffer
);
89 int write_packet(track_t
*track
,
98 long bytes_needed
= track
->bytes_decoded
- ftell(track
->raw_file
);
99 long current_byte
= 0;
101 while(current_byte
< bytes_needed
)
103 // Write packet header
104 float current_time
= start_time
+ (float)current_byte
/ bytes_needed
* (end_time
- start_time
);
105 int packet_bytes
= write_pack_header(mplex
->packet_buffer
,
110 unsigned char *ptr
= mplex
->packet_buffer
+ PACKET_SIZE
- packet_bytes
;
111 int bytes_read
= fread(ptr
, 1, packet_bytes
, track
->raw_file
);
113 result
= !fwrite(mplex
->packet_buffer
, PACKET_SIZE
, 1, mplex
->out_file
);
114 current_byte
+= packet_bytes
;
119 void skip_frame(mpeg3_demuxer_t
*demuxer
)
121 unsigned long header
= 0;
122 mpeg3_title_t
*title
= demuxer
->titles
[demuxer
->current_title
];
126 header
&= 0xffffffff;
127 header
|= mpeg3io_read_char(title
->fs
);
128 }while(header
!= MPEG3_PICTURE_START_CODE
&& !mpeg3io_eof(title
->fs
));
131 * if(!mpeg3io_eof(title->fs))
132 * mpeg3io_seek_relative(title->fs, -4);
134 ((mpeg3_t
*)demuxer
->file
)->last_type_read
= 2;
137 int main(int argc
, char *argv
[])
142 track_t
*atracks
[streams
+ 1];
143 track_t
*vtracks
[streams
+ 1];
144 int total_atracks
= 0;
145 int total_vtracks
= 0;
146 float frame_rate
= 30000.0 / 1001.0;
147 float sample_rate
= 48000;
148 long frames_decoded
= 0;
149 float *audio_temp
= malloc(1);
150 long audio_temp_allocated
= 0;
151 float current_time
= 0, previous_time
= 0;
152 int video_completed
= 0;
153 int audio_completed
= 0;
159 int old_percentage
= 0;
161 path
= malloc(sizeof(char*) * argc
);
162 mplex
.derivative
= 1;
167 printf("Tiny MPLEX by Adam Williams\n");
168 printf("Usage: mplex [-a] <stream 1> <stream2> ... <output>\n");
169 printf(" -a use ac3 packet headers\n");
173 for(i
= 1; i
< argc
; i
++)
175 if(!strcmp(argv
[i
], "-a"))
182 output_path
= argv
[i
];
186 path
[stream
] = malloc(strlen(argv
[i
]) + 1);
187 strcpy(path
[stream
], argv
[i
]);
194 for(stream
= 0; stream
< streams
; stream
++)
196 int is_audio
, is_video
;
197 mpeg3_t
*file
= mpeg3_open(path
[stream
]);
201 printf("Couldn't open %s\n", path
[stream
]);
206 is_audio
= mpeg3_has_audio(file
);
207 is_video
= mpeg3_has_video(file
);
208 mpeg3_set_cpus(file
, 2);
210 if(is_audio
&& is_video
)
212 printf("%s: Can't multiplex a system stream.\n", path
[stream
]);
218 atracks
[total_atracks
] = calloc(1, sizeof(track_t
));
219 atracks
[total_atracks
]->file
= file
;
220 sample_rate
= mpeg3_sample_rate(file
, 0);
221 atracks
[total_atracks
]->raw_file
= fopen(path
[stream
], "rb");
222 atracks
[total_atracks
]->stream_number
= total_atracks
;
228 vtracks
[total_vtracks
] = calloc(1, sizeof(track_t
));
229 vtracks
[total_vtracks
]->file
= file
;
230 frame_rate
= mpeg3_frame_rate(file
, 0);
231 vtracks
[total_vtracks
]->raw_file
= fopen(path
[stream
], "rb");
232 vtracks
[total_vtracks
]->stream_number
= total_vtracks
;
233 // Get the first frame
234 skip_frame(vtracks
[total_vtracks
]->file
->vtrack
[0]->demuxer
);
239 printf("%s: Has neither audio or video.\n", path
[stream
]);
249 printf("You must supply at least 1 video track.\n");
256 if(!(mplex
.out_file
= fopen(output_path
, "wb")))
258 printf("Couldn't open output file\n");
262 // Write multiplexed stream
265 while(!result
&& !(video_completed
&& audio_completed
))
267 previous_time
= current_time
;
268 // Want the frame to come before the audio that goes with it.
269 for(stream
= 0; stream
< total_vtracks
&& !result
; stream
++)
271 // Decode a frame and write it
272 track_t
*track
= vtracks
[stream
];
274 if(!track
->end_of_data
)
277 skip_frame(track
->file
->vtrack
[0]->demuxer
);
278 track
->frames_decoded
++;
279 track
->bytes_decoded
= mpeg3demux_tell(track
->file
->vtrack
[0]->demuxer
);
280 if(track
->frames_decoded
> frames_decoded
)
282 frames_decoded
= track
->frames_decoded
;
283 current_time
= (float)frames_decoded
/ frame_rate
;
286 result
= write_packet(track
,
290 0xe0 | track
->stream_number
,
292 track
->end_of_data
= mpeg3_end_of_video(track
->file
, 0);
293 percentage
= (int)(mpeg3_tell_percentage(track
->file
) * 100);
294 if(percentage
- old_percentage
>= 1)
296 printf("\t%d%% completed\r", percentage
);
297 old_percentage
= percentage
;
303 // Decode audio until the last frame is covered
304 for(stream
= 0; stream
< total_atracks
&& !result
; stream
++)
306 track_t
*track
= atracks
[stream
];
307 //printf("mplex decode audio 1\n");
308 if(!track
->end_of_data
&&
309 (track
->samples_decoded
< current_time
* sample_rate
||
314 long samples_needed
= (long)(current_time
* sample_rate
) - track
->samples_decoded
;
315 if(audio_temp_allocated
< samples_needed
)
318 audio_temp
= malloc(sizeof(float) * samples_needed
);
319 audio_temp_allocated
= samples_needed
;
322 mpeg3_read_audio(track
->file
,
328 track
->bytes_decoded
= mpeg3demux_tell(track
->file
->atrack
[0]->demuxer
);
329 if(!track
->end_of_data
) track
->bytes_decoded
-= 2048;
330 track
->samples_decoded
+= samples_needed
;
331 track
->end_of_data
= mpeg3_end_of_audio(track
->file
, 0);
335 track
->bytes_decoded
= mpeg3demuxer_total_bytes(track
->file
->atrack
[0]->demuxer
);
336 track
->end_of_data
= 1;
339 //printf("mplex decode audio 2\n");
340 result
= write_packet(track
,
344 ac3
? track
->stream_number
: (0xc0 | track
->stream_number
),
349 for(stream
= 0; stream
< total_vtracks
; stream
++)
351 if(vtracks
[stream
]->end_of_data
) video_completed
++;
353 if(video_completed
< total_vtracks
) video_completed
= 0;
355 for(stream
= 0; stream
< total_atracks
; stream
++)
357 if(atracks
[stream
]->end_of_data
) audio_completed
++;
359 if(audio_completed
< total_atracks
) audio_completed
= 0;
364 for(stream
= 0; stream
< total_atracks
; stream
++)
366 mpeg3_close(atracks
[stream
]->file
);
367 fclose(atracks
[stream
]->raw_file
);
368 free(atracks
[stream
]);
371 for(stream
= 0; stream
< total_vtracks
; stream
++)
373 mpeg3_close(vtracks
[stream
]->file
);
374 fclose(vtracks
[stream
]->raw_file
);
375 free(vtracks
[stream
]);
378 if(mplex
.out_file
) fclose(mplex
.out_file
);