+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-
-
-#include "libzmpeg3.h"
-
-#define PACKET_SIZE 2048
-
-class multiplexer_t {
-public:
- int derivative;
- unsigned char packet_buffer[PACKET_SIZE];
- FILE *out_file;
-};
-
-class track_t {
-public:
- void *operator new(size_t n) {
- void *t = (void*) new char[n];
- memset(t,0,n);
- return t;
- }
- void operator delete(void *t,size_t n) {
- delete[](char*)t;
- }
- long bytes_decoded;
- long frames_decoded;
- long samples_decoded;
- mpeg3_t *file;
- FILE *raw_file;
- int stream_number;
- int end_of_data;
-};
-
-int write_pack_header(unsigned char *ptr,
- multiplexer_t *mplex,
- float seconds,
- int stream_id,
- int ac3)
-{
- int packet_length;
-// PACK START CODE
- *ptr++ = 0x00;
- *ptr++ = 0x00;
- *ptr++ = 0x01;
- *ptr++ = 0xba;
-
- if(mplex->derivative == 1)
- {
- unsigned long timestamp = (unsigned long)(seconds * 90000);
- *ptr = 0x20;
- *ptr++ |= ((timestamp & 0xc0000000) >> 29) | 1;
- *ptr++ = (timestamp & 0x3fc00000) >> 22;
- *ptr++ = ((timestamp & 0x003f8000) >> 14) | 1;
- *ptr++ = (timestamp & 0x00007f80) >> 7;
- *ptr++ = ((timestamp & 0x0000007f) << 1) | 1;
-
- *ptr++ = 0;
- *ptr++ = 0;
- *ptr++ = 0;
- }
- else
- if(mplex->derivative == 2)
- {
- *ptr = 0x40;
- }
-
- *ptr++ = 0x00;
- *ptr++ = 0x00;
- *ptr++ = 0x01;
- if(ac3)
- *ptr++ = 0xbd;
- else
- *ptr++ = stream_id;
-
-// Packet length
- packet_length = PACKET_SIZE - (ptr - mplex->packet_buffer) - 2;
- *ptr++ = (packet_length & 0xff00) >> 8;
- *ptr++ = packet_length & 0xff;
-
-// Pts/dts flags
- *ptr++ = 0x0f;
-
-// AC3 stream_id
- if(ac3)
- {
- *ptr++ = stream_id;
- *ptr++ = 0x00;
- *ptr++ = 0x00;
- *ptr++ = 0x00;
- }
-
- return PACKET_SIZE - (ptr - mplex->packet_buffer);
-}
-
-int write_packet(track_t *track,
- float start_time,
- float end_time,
- multiplexer_t *mplex,
- int stream_id,
- int ac3)
-{
- int result = 0;
-
- long bytes_needed = track->bytes_decoded - ftell(track->raw_file);
- long current_byte = 0;
-
- while(current_byte < bytes_needed)
- {
-// Write packet header
- float current_time = start_time + (float)current_byte / bytes_needed * (end_time - start_time);
- int packet_bytes = write_pack_header(mplex->packet_buffer,
- mplex,
- current_time,
- stream_id,
- ac3);
- unsigned char *ptr = mplex->packet_buffer + PACKET_SIZE - packet_bytes;
- /*int bytes_read =*/ fread(ptr, 1, packet_bytes, track->raw_file);
-
- result = !fwrite(mplex->packet_buffer, PACKET_SIZE, 1, mplex->out_file);
- current_byte += packet_bytes;
- }
- return result;
-}
-
-int main(int argc, char *argv[])
-{
- int streams = 0;
- int stream = 0;
- int result = 0;
- track_t *atracks[streams + 1];
- track_t *vtracks[streams + 1];
- int total_atracks = 0;
- int total_vtracks = 0;
- float frame_rate = 30000.0 / 1001.0;
- float sample_rate = 48000;
- long frames_decoded = 0;
- float *audio_temp = new float[1];
- long audio_temp_allocated = 0;
- float current_time = 0, previous_time = 0;
- int video_completed = 0;
- int audio_completed = 0;
- int i;
- int ac3 = 0;
- multiplexer_t mplex;
- char **path;
- char *output_path = 0;
- int old_percentage = 0;
-
- path = new char*[argc];
- mplex.derivative = 1;
- mplex.out_file = 0;
-
- if(argc < 4)
- {
- printf("Tiny MPLEX by Heroine Virtual Ltd.\n");
- printf("Usage: mplex [-a] <stream 1> <stream2> ... <output>\n");
- printf(" -a use ac3 packet headers\n");
- exit(1);
- }
-
- for(i = 1; i < argc; i++)
- {
- if(!strcmp(argv[i], "-a"))
- {
- ac3 = 1;
- }
- else
- if(i == argc - 1)
- {
- output_path = argv[i];
- }
- else
- {
- path[stream] = new char[strlen(argv[i])+1];
- strcpy(path[stream], argv[i]);
- streams++;
- stream++;
- }
- }
-
-// Open files
- for(stream = 0; stream < streams; stream++)
- {
- int is_audio, is_video;
- int error_return;
- mpeg3_t *file = mpeg3_open(path[stream], &error_return);
-
- if(!file)
- {
- printf("Couldn't open %s\n", path[stream]);
- result = 1;
- }
- else
- {
- is_audio = mpeg3_has_audio(file);
- is_video = mpeg3_has_video(file);
- mpeg3_set_cpus(file, 2);
-
- if(is_audio && is_video)
- {
- printf("%s: Can't multiplex a system stream.\n", path[stream]);
- result = 1;
- }
- else
- if(is_audio)
- {
- atracks[total_atracks] = new track_t();
- atracks[total_atracks]->file = file;
- sample_rate = mpeg3_sample_rate(file, 0);
- atracks[total_atracks]->raw_file = fopen(path[stream], "rb");
- atracks[total_atracks]->stream_number = total_atracks;
- total_atracks++;
- }
- else
- if(is_video)
- {
- vtracks[total_vtracks] = new track_t();
- vtracks[total_vtracks]->file = file;
- frame_rate = mpeg3_frame_rate(file, 0);
- vtracks[total_vtracks]->raw_file = fopen(path[stream], "rb");
- vtracks[total_vtracks]->stream_number = total_vtracks;
-// Get the first frame
- mpeg3_skip_video_frame(vtracks[total_vtracks]->file,0);
- total_vtracks++;
- }
- else
- {
- printf("%s: Has neither audio or video.\n", path[stream]);
- result = 1;
- }
- }
- }
-
- if(!result)
- {
- if(!total_vtracks)
- {
- printf("You must supply at least 1 video track.\n");
- result = 1;
- }
- }
-
-// Open output
- if(!result)
- if(!(mplex.out_file = fopen(output_path, "wb")))
- {
- printf("Couldn't open output file\n");
- result = 1;
- }
-
-// Write multiplexed stream
- if(!result)
- {
- while(!result && !(video_completed && audio_completed))
- {
- previous_time = current_time;
-// Want the frame to come before the audio that goes with it.
- for(stream = 0; stream < total_vtracks && !result; stream++)
- {
-// Decode a frame and write it
- track_t *track = vtracks[stream];
-
- if(!track->end_of_data)
- {
- int percentage;
- mpeg3_skip_video_frame(track->file,0);
- track->frames_decoded++;
- track->bytes_decoded = mpeg3_video_tell_byte(track->file,0);
- if(track->frames_decoded > frames_decoded)
- {
- frames_decoded = track->frames_decoded;
- current_time = (float)frames_decoded / frame_rate;
- }
-
- result = write_packet(track,
- previous_time,
- current_time,
- &mplex,
- 0xe0 | track->stream_number,
- 0);
- track->end_of_data = mpeg3_end_of_video(track->file, 0);
- percentage = (int)(mpeg3_video_tell_byte(track->file,0) * 100 /
- mpeg3_get_bytes(track->file));
- if(percentage - old_percentage >= 1)
- {
- printf("\t%d%% completed\r", percentage);
- old_percentage = percentage;
- }
- fflush(stdout);
- }
- }
-
-// Decode audio until the last frame is covered
- for(stream = 0; stream < total_atracks && !result; stream++)
- {
- track_t *track = atracks[stream];
-//printf("mplex decode audio 1\n");
- if(!track->end_of_data &&
- (track->samples_decoded < current_time * sample_rate ||
- video_completed))
- {
- if(!video_completed)
- {
- long samples_needed = (long)(current_time * sample_rate) - track->samples_decoded;
- if(audio_temp_allocated < samples_needed)
- {
- delete [] audio_temp;
- audio_temp = new float[samples_needed];
- audio_temp_allocated = samples_needed;
- }
-
- mpeg3_read_audio(track->file,
- audio_temp,
- 0,
- 0,
- samples_needed,
- 0);
- track->bytes_decoded = mpeg3_audio_tell_byte(track->file,0);
- if(!track->end_of_data) track->bytes_decoded -= 2048;
- track->samples_decoded += samples_needed;
- track->end_of_data = mpeg3_end_of_audio(track->file, 0);
- }
- else
- {
- track->bytes_decoded = mpeg3_get_bytes(track->file);
- track->end_of_data = 1;
- }
-
-//printf("mplex decode audio 2\n");
- result = write_packet(track,
- previous_time,
- current_time,
- &mplex,
- ac3 ? track->stream_number : (0xc0 | track->stream_number),
- ac3);
- }
- }
-
- for(stream = 0; stream < total_vtracks; stream++)
- {
- if(vtracks[stream]->end_of_data) video_completed++;
- }
- if(video_completed < total_vtracks) video_completed = 0;
-
- for(stream = 0; stream < total_atracks; stream++)
- {
- if(atracks[stream]->end_of_data) audio_completed++;
- }
- if(audio_completed < total_atracks) audio_completed = 0;
- }
- }
-
-// Close streams
- for(stream = 0; stream < total_atracks; stream++)
- {
- mpeg3_close(atracks[stream]->file);
- fclose(atracks[stream]->raw_file);
- delete atracks[stream];
- }
-
- for(stream = 0; stream < total_vtracks; stream++)
- {
- mpeg3_close(vtracks[stream]->file);
- fclose(vtracks[stream]->raw_file);
- delete vtracks[stream];
- }
-
- if(mplex.out_file) fclose(mplex.out_file);
-
- return result;
-}
-
-