www.pudn.com > avi 到 mpeg 的转换程序及源代码.zip > MULTPLEX.C
/*************************************************************************
* mplex - MPEG/SYSTEMS multiplexer *
* Copyright (C) 1994 1995 Christoph Moar *
* Siemens ZFE ST SN 11 / T SN 6 *
* *
* moar@informatik.tu-muenchen.de *
* (Christoph Moar) *
* klee@heaven.zfe.siemens.de *
* (Christian Kleegrewe, Siemens only requests) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
*************************************************************************/
/*
* 4/4/97 - John Schlichther
*
* extensively altered to create avi2mpg1 - avi to mpeg-1 encoder
*
* Since avi file, and the avi subsystem are platform dependant, cross
* platform compatibility removed, many optional features disabled or
* removed, code generally trimmed to a minimum.
*
*/
#include "mplex.h"
#ifdef TIMER
extern long total_sec;
extern long total_usec;
extern long global_sec;
extern long global_usec;
extern struct timeval tp_start;
extern struct timeval tp_end;
extern struct timeval tp_global_start;
extern struct timeval tp_global_end;
#endif
extern unsigned int vcd_parm;
/******************************************************************
Hauptschleife Multiplexroutinenaufruf
Kuemmert sich um oeffnen und schliessen alles beteiligten
Dateien und um den korrekten Aufruf der jeweils
noetigen Video- und Audio-Packet Routinen.
Gewissermassen passiert hier das Wesentliche des
Multiplexens. Die Bufferkapazitaeten und die TimeStamps
werden ueberprueft und damit entschieden, ob ein Video-
Audio- oder Padding-Packet erstellt und geschrieben
werden soll.
Main multiplex iteration.
Opens and closes all needed files and manages the correct
call od the respective Video- and Audio- packet routines.
The basic multiplexing is done here. Buffer capacity and
Timestamp checking is also done here, decision is taken
wether we should genereate a Video-, Audio- or Padding-
packet.
******************************************************************/
void outputstream (video_file, video_units, video_info,
audio_file, audio_units, audio_info,
multi_file, which_streams )
char *video_file;
char *video_units;
Video_struc *video_info;
char *audio_file;
char *audio_units;
Audio_struc *audio_info;
char *multi_file;
unsigned int which_streams;
{
FILE *istream_v; /* Inputstream Video */
FILE *istream_a; /* Inputstream Audio */
FILE *ostream; /* Outputstream MPEG */
FILE *vunits_info; /* Input Video Units */
FILE *aunits_info; /* Input Audio Units */
Vaunit_struc video_au; /* Video Access Unit */
Aaunit_struc audio_au; /* Audio Access Unit */
unsigned int data_rate=0; /* AudioVideo Byterate */
unsigned int video_rate=0;
unsigned int audio_rate=0;
double delay,audio_delay,video_delay;
double clock_cycles;
double audio_next_clock_cycles;
double video_next_clock_cycles;
unsigned int bytes_output;
double dmux_rate;
unsigned long sectors_delay,video_delay_ms,audio_delay_ms;
unsigned int mux_rate;
unsigned char picture_start;
unsigned char audio_frame_start;
//unsigned int bytes_left;
unsigned int audio_bytes;
unsigned int video_bytes;
unsigned int nsec_a=0;
unsigned int nsec_v=0;
unsigned int nsec_p=0;
unsigned char* index;
Timecode_struc SCR_audio_delay;
Timecode_struc SCR_video_delay;
Timecode_struc current_SCR;
Timecode_struc audio_next_SCR;
Timecode_struc video_next_SCR;
Buffer_struc video_buffer;
Buffer_struc audio_buffer;
Pack_struc pack;
Sys_header_struc sys_header;
Sector_struc sector;
//Timecode_struc timestamp;
unsigned long sector_size;
unsigned long min_packet_data;
unsigned long max_packet_data;
unsigned long packets_per_pack;
unsigned long audio_buffer_size;
unsigned long video_buffer_size;
unsigned long write_pack;
unsigned char marker_pack;
unsigned long packet_data_size;
unsigned char verbose;
/* Oeffne alle Ein- und Ausgabefiles */
/* Open in- and outputstream */
if (which_streams & STREAMS_VIDEO) istream_v = fopen (video_file, "rb");
if (which_streams & STREAMS_AUDIO) istream_a = fopen (audio_file, "rb");
if (which_streams & STREAMS_VIDEO) vunits_info = fopen (video_units, "rb");
if (which_streams & STREAMS_AUDIO) aunits_info = fopen (audio_units, "rb");
ostream = fopen (multi_file, "wb");
/* Einlesen erster Access Unit Informationen */
/* read in first access unit information */
picture_start = FALSE;
audio_frame_start = FALSE;
empty_vaunit_struc (&video_au);
empty_aaunit_struc (&audio_au);
if (which_streams & STREAMS_AUDIO) {
fread (&audio_au, sizeof(Aaunit_struc), 1, aunits_info);
audio_frame_start = TRUE;
}
if (which_streams & STREAMS_VIDEO) {
fread (&video_au, sizeof(Vaunit_struc), 1, vunits_info);
picture_start = TRUE;
}
//printf("\nMerging elementary streams to MPEG/SYSTEMS multiplexed stream.\n");
//printf("\n+------------------ MPEG/SYSTEMS INFORMATION -----------------+\n");
//do
//{
//printf ("\nsector size (CD-ROM 2324 bytes) : 4096");
//scanf ("%ld", §or_size);
if(vcd_parm)
sector_size = 2324;
else
sector_size = 2048;
//} while (sector_size>MAX_SECTOR_SIZE);
//printf ("\npacks to packets ratio 1 : 1");
//scanf ("%ld", &packets_per_pack);
packets_per_pack = 1;
//printf ("\nSTD video buffer in kB (CSPS: max 46 kB) : ");
//scanf ("%ld", &video_buffer_size);
if(vcd_parm)
video_buffer_size = 40;
else
video_buffer_size = 46;
//printf ("\nSTD audio buffer in kB (CSPS: max 4 kB) : ");
//scanf ("%ld", &audio_buffer_size);
audio_buffer_size = 4;
write_pack = packets_per_pack;
video_buffer_size *= 1024;
audio_buffer_size *= 1024;
min_packet_data = sector_size - PACK_HEADER_SIZE - SYS_HEADER_SIZE -
PACKET_HEADER_SIZE - AFTER_PACKET_LENGTH;
max_packet_data = sector_size - PACKET_HEADER_SIZE - AFTER_PACKET_LENGTH;
/* if we have only one stream, we have 3 more bytes in the sys header free */
if (which_streams != STREAMS_BOTH) {
min_packet_data += 3;
}
/* Bufferstrukturen Initialisieren */
/* initialize buffer structure */
init_buffer_struc (&video_buffer,video_buffer_size);
init_buffer_struc (&audio_buffer,audio_buffer_size);
/* DTS ist in den ersten Units i.d.R. gleich null. Damit
kein Bufferunterlauf passiert, muss berechnet werden,
wie lange es dauert, bis alle Daten sowohl des ersten
Video- als auch des ersten Audio-Access units ankommen.
Diesen Wert dann als Art Startup-Delay zu den Time-
stamps dazurechnen. Um etwas Spielraum zu haben, wird
als Wert einfach die Anzahl der zu uebertragenden
Sektoren aufgerundet. */
/* DTS of the first units is supposed to be zero. To avoid
Buffer underflow, we have to compute how long it takes for
all first Video and Audio access units to arrive at the
system standard decoder buffer. This delay is added as a
kind of startup delay to all of the TimeStamps. We compute
a ceiling based on the number of sectors we will have
to transport for the first access units */
if (which_streams & STREAMS_VIDEO) {
if (video_info->bit_rate > video_info->comp_bit_rate)
video_rate = video_info->bit_rate * 50;
else
video_rate = video_info->comp_bit_rate * 50;
}
if (which_streams & STREAMS_AUDIO)
audio_rate = bitrate_index[3-audio_info->layer][audio_info->bit_rate]*128;
data_rate = video_rate + audio_rate;
dmux_rate = ceil((double)(data_rate) *
((double)(sector_size)/(double)(min_packet_data) +
((double)(sector_size)/(double)(max_packet_data) *
(double)(packets_per_pack-1.))) / (double)(packets_per_pack) );
data_rate = (unsigned int)ceil(dmux_rate/50.)*50;
//printf ("\ncomputed multiplexed stream data rate : %7.3f\n",dmux_rate);
//printf ("target data rate (e.g. %6u) : ",data_rate);
//scanf ("%lf", &dmux_rate);
if(vcd_parm)
dmux_rate = 176400;
//printf ("\nstartup sectors_delay : 8");
//scanf ("%u", §ors_delay);
sectors_delay = 8;
//printf ("\nvideo stream startup offset (ms) : 0");
//scanf ("%u", &video_delay_ms);
video_delay_ms = 0;
//printf ("\naudio stream startup offset (ms) : 0");
//scanf ("%u", &audio_delay_ms);
audio_delay_ms = 0;
video_delay = (double)video_delay_ms*(double)(CLOCKS/1000);
audio_delay = (double)audio_delay_ms*(double)(CLOCKS/1000);
//verbose=ask_verbose();
verbose=FALSE;
//printf ("\n");
#ifdef TIMER
gettimeofday (&tp_global_start,NULL);
#endif
mux_rate = (unsigned int)ceil(dmux_rate/50.);
dmux_rate= mux_rate * 50.;
delay = ((double)sectors_delay +
ceil((double)video_au.length/(double)min_packet_data) +
ceil((double)audio_au.length/(double)min_packet_data )) *
(double)sector_size/dmux_rate*(double)CLOCKS;
audio_delay += delay;
video_delay += delay;
make_timecode (audio_delay, &SCR_audio_delay);
make_timecode (video_delay, &SCR_video_delay);
add_to_timecode (&SCR_video_delay, &video_au.DTS);
add_to_timecode (&SCR_video_delay, &video_au.PTS);
add_to_timecode (&SCR_audio_delay, &audio_au.PTS);
bytes_output = 0;
/* Jetzt probieren wir mal, Unit fuer Unit auszulesen und
ins Outputstream auszuschreiben. Die Schwierigkeit liegt
darin, dass die Buffer konstant ueberprueft werden muessen
und dass die jeweilige Access Unit auch innerhalb des DTS
eintreten muss. Es kann passieren, dass z.B. im Video-
Buffer noch ein altes Picture liegt, das noch dekodiert
werden muss, wir jetzt schon das naechste schicken, aber
nach einigen Packets der Buffer voll ist. Da darf nichts
mehr geschickt werden, bis die DTS des alten Bildes
eingetreten ist und damit der Buffer kleiner geworden ist.
In der Zwischenzeit kann ein Audio-Packet geschickt werden
und/oder ein Padding-Packet generiert werden. */
/* Let's try to read in unit after unit and to write it out into
the outputstream. The only difficulty herein lies into the
buffer management, and into the fact the the actual access
unit *has* to arrive in time, that means the whole unit
(better yet, packet data), has to arrive before arrival of
DTS. If both buffers are full we'll generate a padding packet */
//status_header ();
while ((video_au.length + audio_au.length) > 0)
{
if (write_pack-- == packets_per_pack)
{
marker_pack = TRUE;
packet_data_size = min_packet_data;
} else
{
marker_pack = FALSE;
packet_data_size = max_packet_data;
}
if (write_pack == 0) write_pack = packets_per_pack;
audio_bytes = (audio_au.length/min_packet_data)*sector_size +
(audio_au.length%min_packet_data)+(sector_size-min_packet_data);
video_bytes = (video_au.length/min_packet_data)*sector_size +
(video_au.length%min_packet_data)+(sector_size-min_packet_data);
clock_cycles = (double)(bytes_output+LAST_SCR_BYTE_IN_PACK)*
CLOCKS/dmux_rate;
audio_next_clock_cycles = (double)(bytes_output+sector_size+
audio_bytes)/dmux_rate*CLOCKS;
video_next_clock_cycles = (double)(bytes_output+sector_size+
video_bytes)/dmux_rate*CLOCKS;
make_timecode (clock_cycles, ¤t_SCR);
make_timecode (audio_next_clock_cycles, &audio_next_SCR);
make_timecode (video_next_clock_cycles, &video_next_SCR);
if (which_streams & STREAMS_AUDIO) buffer_clean (&audio_buffer, ¤t_SCR);
if (which_streams & STREAMS_VIDEO) buffer_clean (&video_buffer, ¤t_SCR);
/* FALL: Video Buffer OK, Video Daten vorhanden */
/* Audio Daten werden on time ankommen */
/* CASE: Video Buffer OK, Video Data ready */
/* Audio Data will arrive on time */
if ( (buffer_space (&video_buffer) >= packet_data_size)
&& (video_au.length>0)
&& ((comp_timecode (&audio_next_SCR, &audio_au.PTS)) ||
(audio_au.length==0) ))
{
/* video packet schicken */
/* write out video packet */
output_video (¤t_SCR, &SCR_video_delay, vunits_info,
istream_v, ostream, &pack, &sys_header, §or,
&video_buffer, &video_au, &picture_start,
&bytes_output, mux_rate, audio_buffer_size, video_buffer_size,
packet_data_size, marker_pack, which_streams);
/* status info */
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
//status_info (nsec_a, ++nsec_v, nsec_p, bytes_output,
// buffer_space(&video_buffer),
// buffer_space(&audio_buffer),verbose);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
}
/* FALL: Audio Buffer OK, Audio Daten vorhanden */
/* Video Daten werden on time ankommen */
/* CASE: Audio Buffer OK, Audio Data ready */
/* Video Data will arrive on time */
else if ( (buffer_space (&audio_buffer) >= packet_data_size)
&& (audio_au.length>0)
&& ((comp_timecode (&video_next_SCR, &video_au.DTS)) ||
(video_au.length==0) ))
{
/* audio packet schicken */
/* write out audio packet */
output_audio (¤t_SCR, &SCR_audio_delay, aunits_info,
istream_a, ostream, &pack, &sys_header, §or,
&audio_buffer, &audio_au, &audio_frame_start,
&bytes_output, mux_rate, audio_buffer_size, video_buffer_size,
packet_data_size, marker_pack, which_streams);
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
/* status info */
//status_info (++nsec_a, nsec_v, nsec_p, bytes_output,
// buffer_space(&video_buffer),
// buffer_space(&audio_buffer),verbose);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
}
/* FALL: Audio Buffer OK, Audio Daten vorhanden */
/* Audio Daten werden nicht on time ankommen */
/* CASE: Audio Buffer OK, Audio data ready */
/* Audio data will be time out */
else if ( (buffer_space (&audio_buffer) >= packet_data_size)
&& (audio_au.length>0)
&! comp_timecode (&audio_next_SCR, &audio_au.PTS))
{
/* audio packet schicken */
/* write out audio packet */
output_audio (¤t_SCR, &SCR_audio_delay, aunits_info,
istream_a, ostream, &pack, &sys_header, §or,
&audio_buffer, &audio_au, &audio_frame_start,
&bytes_output, mux_rate, audio_buffer_size, video_buffer_size,
packet_data_size, marker_pack, which_streams);
/* audio fehlermeldung */
/* audio error message */
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
status_message (STATUS_AUDIO_TIME_OUT);
/* status info */
//status_info (++nsec_a, nsec_v, nsec_p, bytes_output,
// buffer_space(&video_buffer),
// buffer_space(&audio_buffer),verbose);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
}
/* FALL: Video Buffer OK, Video Daten vorhanden */
/* Video Daten werden nicht on time ankommen */
/* CASE: Video Buffer OK, Video data ready */
/* Video data will be time out */
else if ( (buffer_space (&video_buffer) >= packet_data_size)
&& (video_au.length>0)
&! comp_timecode (&video_next_SCR, &video_au.DTS))
{
/* video packet schicken */
/* write out video packet */
output_video (¤t_SCR, &SCR_video_delay, vunits_info,
istream_v, ostream, &pack, &sys_header, §or,
&video_buffer, &video_au, &picture_start,
&bytes_output, mux_rate, audio_buffer_size, video_buffer_size,
packet_data_size, marker_pack, which_streams);
/* video fehlermeldung */
/* video error message */
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
status_message (STATUS_VIDEO_TIME_OUT);
/* status info */
//status_info (nsec_a, ++nsec_v, nsec_p, bytes_output,
// buffer_space(&video_buffer),
// buffer_space(&audio_buffer),verbose);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
}
/* FALL: Audio Buffer nicht OK */
/* Video Buffer nicht OK */
/* CASE: Audio Buffer NOT OK */
/* Video Buffer NOT OK */
else
{
/* padding packet schicken */
/* write out padding packet */
output_padding (¤t_SCR, ostream, &pack, &sys_header,
§or, &bytes_output, mux_rate, audio_buffer_size,
video_buffer_size,packet_data_size, marker_pack, which_streams);
/* status info */
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
//status_info (nsec_a, nsec_v, ++nsec_p, bytes_output,
// buffer_space(&video_buffer),
// buffer_space(&audio_buffer),verbose);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
}
}
/* ISO 11172 END CODE schreiben */
/* write out ISO 11172 END CODE */
index = sector.buf;
*(index++) = (unsigned char)((ISO11172_END)>>24);
*(index++) = (unsigned char)((ISO11172_END & 0x00ff0000)>>16);
*(index++) = (unsigned char)((ISO11172_END & 0x0000ff00)>>8);
*(index++) = (unsigned char)(ISO11172_END & 0x000000ff);
fwrite (sector.buf, sizeof (unsigned char), 4, ostream);
bytes_output += 4;
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
/* status info*/
//status_info (nsec_a, nsec_v, nsec_p, bytes_output,
// buffer_space(&video_buffer),
// buffer_space(&audio_buffer),verbose);
if (!verbose) printf ("\n");
//status_footer ();
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
/* Schliesse alle Ein- und Ausgabefiles */
/* close all In- and Outputfiles */
fclose (ostream);
if (which_streams & STREAMS_AUDIO) fclose (aunits_info);
if (which_streams & STREAMS_VIDEO) fclose (vunits_info);
if (which_streams & STREAMS_AUDIO) fclose (istream_a);
if (which_streams & STREAMS_VIDEO) fclose (istream_v);
/* loeschen der temporaeren Files */
/* delete tmp files */
if (which_streams & STREAMS_VIDEO) unlink (video_units);
if (which_streams & STREAMS_AUDIO) unlink (audio_units);
//printf ("\nDone, tmp files removed.\n\n");
#ifdef TIMER
gettimeofday (&tp_global_end, NULL);
global_sec = 10*(tp_global_end.tv_sec - tp_global_start.tv_sec);
global_usec= 10*(tp_global_end.tv_usec - tp_global_start.tv_usec);
global_sec += (global_usec / 100000);
total_sec *= 10;
total_sec += (total_usec / 100000);
printf ("Timing global: %10.1f secs\n",(float)global_sec/10.);
printf ("Timing IO : %10.1f secs\n",(float)total_sec/10.);
#endif
}
/******************************************************************
Next_Video_Access_Unit
holt aus dem TMP File, der die Info's ueber die Access
Units enthaelt, die jetzt gueltige Info her. Nach
dem Erstellen des letzten Packs sind naemlich eine
bestimmte Anzahl Bytes und damit AU's eingelesen worden.
gets information for the next access unit from the tmp
file
******************************************************************/
void next_video_access_unit (buffer, video_au, bytes_left, vunits_info,
picture_start, SCR_delay)
Buffer_struc *buffer;
Vaunit_struc *video_au;
unsigned int *bytes_left;
FILE *vunits_info;
unsigned char *picture_start;
Timecode_struc *SCR_delay;
{
int i;
if (*bytes_left == 0)
return;
while (video_au->length < *bytes_left)
{
queue_buffer (buffer, video_au->length, &video_au->DTS);
*bytes_left -= video_au->length;
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
i=fread (video_au, sizeof(Vaunit_struc), 1, vunits_info);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
if (i != 1)
{
empty_vaunit_struc (video_au);
//status_message(STATUS_VIDEO_END);
return;
}
*picture_start = TRUE;
add_to_timecode (SCR_delay, &video_au->DTS);
add_to_timecode (SCR_delay, &video_au->PTS);
};
if (video_au->length > *bytes_left)
{
queue_buffer (buffer, *bytes_left, &video_au->DTS);
video_au->length -= *bytes_left;
*picture_start = FALSE;
} else
if (video_au->length == *bytes_left)
{
queue_buffer (buffer, *bytes_left, &video_au->DTS);
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
i=fread (video_au, sizeof(Vaunit_struc), 1, vunits_info);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
if (i != 1)
{
empty_vaunit_struc (video_au);
//status_message(STATUS_VIDEO_END);
return;
}
*picture_start = TRUE;
add_to_timecode (SCR_delay, &video_au->DTS);
add_to_timecode (SCR_delay, &video_au->PTS);
};
}
/******************************************************************
Output_Video
generiert Pack/Sys_Header/Packet Informationen aus dem
Video Stream und speichert den so erhaltenen Sektor ab.
generates Pack/Sys_Header/Packet information from the
video stream and writes out the new sector
******************************************************************/
void output_video (SCR, SCR_delay, vunits_info, istream_v, ostream,
pack, sys_header, sector, buffer, video_au,
picture_start, bytes_output, mux_rate,
audio_buffer_size, video_buffer_size,
packet_data_size, marker_pack, which_streams)
Timecode_struc *SCR;
Timecode_struc *SCR_delay;
FILE *vunits_info;
FILE *istream_v;
FILE *ostream;
Pack_struc *pack;
Sys_header_struc *sys_header;
Sector_struc *sector;
Buffer_struc *buffer;
Vaunit_struc *video_au;
unsigned char *picture_start;
unsigned int *bytes_output;
unsigned int mux_rate;
unsigned long audio_buffer_size;
unsigned long video_buffer_size;
unsigned long packet_data_size;
unsigned char marker_pack;
unsigned int which_streams;
{
unsigned int bytes_left;
unsigned int temp;
Pack_struc *pack_ptr;
Sys_header_struc *sys_header_ptr;
unsigned char timestamps;
if (marker_pack)
{
/* Wir generieren den Pack Header */
/* let's generate pack header */
create_pack (pack, SCR, mux_rate);
/* Wir generieren den System Header */
/* let's generate system header */
create_sys_header (sys_header, mux_rate, 1, 1, 1, 1, 1, 1,
AUDIO_STR_0, 0, audio_buffer_size/128,
VIDEO_STR_0, 1, video_buffer_size/1024, which_streams );
pack_ptr = pack;
sys_header_ptr = sys_header;
} else
{
pack_ptr = NULL;
sys_header_ptr = NULL;
}
/* Wir generieren das Packet */
/* let's generate packet */
/* faengt im Packet ein Bild an? */
/* does a frame start in this packet? */
/* FALL: Packet beginnt mit neuer Access Unit */
/* CASE: Packet starts with new access unit */
if (*picture_start)
{
if (video_au->type == BFRAME)
timestamps=TIMESTAMPS_PTS;
else
timestamps=TIMESTAMPS_PTS_DTS;
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
istream_v, VIDEO_STR_0, 1, video_buffer_size/1024,
TRUE, &video_au->PTS, &video_au->DTS,
timestamps, which_streams );
bytes_left = sector->length_of_packet_data;
next_video_access_unit (buffer, video_au, &bytes_left, vunits_info,
picture_start, SCR_delay);
}
/* FALL: Packet beginnt mit alter Access Unit, es kommt */
/* keine neue im selben Packet vor */
/* CASE: Packet begins with old access unit, no new one */
/* begins in the very same packet */
else if (!(*picture_start) && (video_au->length >= packet_data_size))
{
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
istream_v, VIDEO_STR_0, 1, video_buffer_size/1024,
TRUE, NULL, NULL,
TIMESTAMPS_NO, which_streams );
bytes_left = sector->length_of_packet_data;
next_video_access_unit (buffer, video_au, &bytes_left, vunits_info,
picture_start, SCR_delay);
}
/* FALL: Packet beginnt mit alter Access Unit, es kommt */
/* eine neue im selben Packet vor */
/* CASE: Packet begins with old access unit, a new one */
/* begins in the very same packet */
else if (!(*picture_start) && (video_au->length < packet_data_size))
{
temp = video_au->length;
queue_buffer (buffer, video_au->length, &video_au->DTS);
/* gibt es ueberhaupt noch eine Access Unit ? */
/* is there a new access unit anyway? */
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
if (fread (video_au, sizeof(Vaunit_struc), 1, vunits_info)==1)
{
if (video_au->type == BFRAME)
timestamps=TIMESTAMPS_PTS;
else
timestamps=TIMESTAMPS_PTS_DTS;
*picture_start = TRUE;
add_to_timecode (SCR_delay, &video_au->DTS);
add_to_timecode (SCR_delay, &video_au->PTS);
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
istream_v, VIDEO_STR_0, 1, video_buffer_size/1024,
TRUE, &video_au->PTS, &video_au->DTS,
timestamps, which_streams );
bytes_left = sector->length_of_packet_data - temp;
next_video_access_unit (buffer, video_au, &bytes_left, vunits_info,
picture_start, SCR_delay);
} else
{
//status_message(STATUS_VIDEO_END);
empty_vaunit_struc (video_au);
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
istream_v, VIDEO_STR_0, 1, video_buffer_size/1024,
TRUE, NULL, NULL,
TIMESTAMPS_NO, which_streams );
};
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
}
/* Sector auf Platte schreiben */
/* write out sector */
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
fwrite (sector->buf, sector->length_of_sector, 1, ostream);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
*bytes_output += sector->length_of_sector;
}
/******************************************************************
Next_Audio_Access_Unit
holt aus dem TMP File, der die Info's ueber die Access
Units enthaelt, die jetzt gueltige Info her. Nach
dem Erstellen des letzten Packs sind naemlich eine
bestimmte Anzahl Bytes und damit AU's eingelesen worden.
gets information on access unit from the tmp file
******************************************************************/
void next_audio_access_unit (buffer, audio_au, bytes_left, aunits_info,
audio_frame_start, SCR_delay)
Buffer_struc *buffer;
Aaunit_struc *audio_au;
unsigned int *bytes_left;
FILE *aunits_info;
unsigned char *audio_frame_start;
Timecode_struc *SCR_delay;
{
int i;
if (*bytes_left == 0)
return;
while (audio_au->length < *bytes_left)
{
queue_buffer (buffer, audio_au->length, &audio_au->PTS);
*bytes_left -= audio_au->length;
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
i=fread (audio_au, sizeof(Aaunit_struc), 1, aunits_info);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
if (i != 1)
{
empty_aaunit_struc (audio_au);
//status_message(STATUS_AUDIO_END);
return;
}
*audio_frame_start = TRUE;
add_to_timecode (SCR_delay, &audio_au->PTS);
};
if (audio_au->length > *bytes_left)
{
queue_buffer (buffer, *bytes_left, &audio_au->PTS);
audio_au->length -= *bytes_left;
*audio_frame_start = FALSE;
} else
if (audio_au->length == *bytes_left)
{
queue_buffer (buffer, *bytes_left, &audio_au->PTS);
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
i=fread (audio_au, sizeof(Aaunit_struc), 1, aunits_info);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
if (i != 1)
{
empty_aaunit_struc (audio_au);
//status_message(STATUS_AUDIO_END);
return;
}
*audio_frame_start = TRUE;
add_to_timecode (SCR_delay, &audio_au->PTS);
};
}
/******************************************************************
Output_Audio
erstellt Pack/Sys_Header/Packet Informationen aus dem
Audio Stream und speichert den so erhaltenen Sector ab.
generates Pack/Sys Header/Packet information from the
audio stream and saves them into the sector
******************************************************************/
void output_audio (SCR, SCR_delay, aunits_info, istream_a, ostream,
pack, sys_header, sector, buffer, audio_au,
audio_frame_start, bytes_output, mux_rate,
audio_buffer_size, video_buffer_size,
packet_data_size, marker_pack, which_streams)
Timecode_struc *SCR;
Timecode_struc *SCR_delay;
FILE *aunits_info;
FILE *istream_a;
FILE *ostream;
Pack_struc *pack;
Sys_header_struc *sys_header;
Sector_struc *sector;
Buffer_struc *buffer;
Aaunit_struc *audio_au;
unsigned char *audio_frame_start;
unsigned int *bytes_output;
unsigned int mux_rate;
unsigned long audio_buffer_size;
unsigned long video_buffer_size;
unsigned long packet_data_size;
unsigned char marker_pack;
unsigned int which_streams;
{
unsigned int bytes_left;
unsigned int temp;
Pack_struc *pack_ptr;
Sys_header_struc *sys_header_ptr;
if (marker_pack)
{
/* Wir generieren den Pack Header */
/* let's generate pack header */
create_pack (pack, SCR, mux_rate);
/* Wir generieren den System Header */
/* let's generate system header */
create_sys_header (sys_header, mux_rate, 1, 1, 1, 1, 1, 1,
AUDIO_STR_0, 0, audio_buffer_size/128,
VIDEO_STR_0, 1, video_buffer_size/1024, which_streams );
pack_ptr = pack;
sys_header_ptr = sys_header;
}
else
{
pack_ptr = NULL;
sys_header_ptr = NULL;
}
/* Wir generieren das Packet */
/* Let's generate packet */
/* faengt im Packet ein Audio Frame an? */
/* does a audio frame start in this packet? */
/* FALL: Packet beginnt mit neuer Access Unit */
/* CASE: packet starts with new access unit */
if (*audio_frame_start)
{
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
istream_a, AUDIO_STR_0, 0, audio_buffer_size/128,
TRUE, &audio_au->PTS, NULL,
TIMESTAMPS_PTS, which_streams);
bytes_left = sector->length_of_packet_data;
next_audio_access_unit (buffer, audio_au, &bytes_left, aunits_info,
audio_frame_start, SCR_delay);
}
/* FALL: Packet beginnt mit alter Access Unit, es kommt */
/* keine neue im selben Packet vor */
/* CASE: packet starts with old access unit, no new one */
/* starts in this very same packet */
else if (!(*audio_frame_start) && (audio_au->length >= packet_data_size))
{
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
istream_a, AUDIO_STR_0, 0, audio_buffer_size/128,
TRUE, NULL, NULL,
TIMESTAMPS_NO, which_streams );
bytes_left = sector->length_of_packet_data;
next_audio_access_unit (buffer, audio_au, &bytes_left, aunits_info,
audio_frame_start, SCR_delay);
}
/* FALL: Packet beginnt mit alter Access Unit, es kommt */
/* eine neue im selben Packet vor */
/* CASE: packet starts with old access unit, a new one */
/* starts in this very same packet */
else if (!(*audio_frame_start) && (audio_au->length < packet_data_size))
{
temp = audio_au->length;
queue_buffer (buffer, audio_au->length, &audio_au->PTS);
/* gibt es ueberhaupt noch eine Access Unit ? */
/* is there another access unit anyway ? */
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
if (fread (audio_au, sizeof(Aaunit_struc), 1, aunits_info)==1)
{
*audio_frame_start = TRUE;
add_to_timecode (SCR_delay, &audio_au->PTS);
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
istream_a, AUDIO_STR_0, 0, audio_buffer_size/128,
TRUE, &audio_au->PTS, NULL,
TIMESTAMPS_PTS, which_streams );
bytes_left = sector->length_of_packet_data - temp;
next_audio_access_unit (buffer, audio_au, &bytes_left, aunits_info,
audio_frame_start, SCR_delay);
} else
{
//status_message(STATUS_AUDIO_END);
empty_aaunit_struc (audio_au);
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
istream_a, AUDIO_STR_0, 0, audio_buffer_size/128,
TRUE, NULL, NULL,
TIMESTAMPS_NO, which_streams );
};
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
}
/* Sector auf Platte schreiben */
/* write out sector onto disk */
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
fwrite (sector->buf, sector->length_of_sector, 1, ostream);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
*bytes_output += sector->length_of_sector;
}
/******************************************************************
Output_Padding
erstellt Pack/Sys_Header/Packet Informationen zu einem
Padding-Stream und speichert den so erhaltenen Sector ab.
generates Pack/Sys Header/Packet information for a
padding stream and saves the sector
******************************************************************/
void output_padding (SCR, ostream,
pack, sys_header, sector, bytes_output, mux_rate,
audio_buffer_size, video_buffer_size,
packet_data_size, marker_pack, which_streams)
Timecode_struc *SCR;
FILE *ostream;
Pack_struc *pack;
Sys_header_struc *sys_header;
Sector_struc *sector;
unsigned int *bytes_output;
unsigned int mux_rate;
unsigned long audio_buffer_size;
unsigned long video_buffer_size;
unsigned long packet_data_size;
unsigned char marker_pack;
unsigned int which_streams;
{
//unsigned int bytes_left;
//unsigned int temp;
Pack_struc *pack_ptr;
Sys_header_struc *sys_header_ptr;
if (marker_pack)
{
/* Wir generieren den Pack Header */
/* let's generate the pack header */
create_pack (pack, SCR, mux_rate);
/* Wir generieren den System Header */
/* let's generate the system header */
create_sys_header (sys_header, mux_rate, 1, 1, 1, 1, 1, 1,
AUDIO_STR_0, 0, audio_buffer_size/128,
VIDEO_STR_0, 1, video_buffer_size/1024, which_streams );
pack_ptr = pack;
sys_header_ptr = sys_header;
}
else
{
pack_ptr = NULL;
sys_header_ptr = NULL;
}
/* Wir generieren das Packet */
/* let's generate the packet */
create_sector (sector, pack_ptr, sys_header_ptr,
packet_data_size+PACKET_HEADER_SIZE+AFTER_PACKET_LENGTH,
NULL, PADDING_STR, 0, 0,
FALSE, NULL, NULL,
TIMESTAMPS_NO, which_streams );
#ifdef TIMER
gettimeofday (&tp_start,NULL);
#endif
fwrite (sector->buf, sector->length_of_sector*sizeof (unsigned char), 1,
ostream);
#ifdef TIMER
gettimeofday (&tp_end,NULL);
total_sec += (tp_end.tv_sec - tp_start.tv_sec);
total_usec += (tp_end.tv_usec - tp_start.tv_usec);
#endif
*bytes_output += sector->length_of_sector;
}