www.pudn.com > avi 到 mpeg 的转换程序及源代码.zip > INPTSTRM.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"
/*************************************************************************
MPEG Streams Kontrolle
Basic Checks on MPEG Streams
*************************************************************************/
void marker_bit (bs, what)
Bit_stream_struc *bs;
unsigned int what;
{
if (what != get1bit(bs))
{
printf ("\nError in MPEG stream at offset (bits) %ul: supposed marker bit not found.\n",sstell(bs));
exit (1);
}
}
/*************************************************************************
MPEG Verifikation der Inputfiles
Check if files are valid MPEG streams
*************************************************************************/
void check_files (vfile, afile, mfile, audio_file, video_file, multi_file,
audio_bytes, video_bytes, ptr_which_streams)
char *vfile, *afile, *mfile;
char** audio_file;
char** video_file;
char** multi_file;
unsigned int *audio_bytes;
unsigned int *video_bytes;
unsigned int *ptr_which_streams;
{
Bit_stream_struc bs1, bs2;
unsigned int bytes_1, bytes_2;
if (open_file(vfile, &bytes_1) || open_file(afile, &bytes_2))
exit (1);
open_bit_stream_r (&bs1, vfile, BUFFER_SIZE);
open_bit_stream_r (&bs2, afile, BUFFER_SIZE);
/* Das Bitstreampaket kuemmert sich bei einem look_ahead nicht
darum, den Buffer vorzubereiten, weil es davon ausgeht, dass
vorher mindestens einmal ein getbits () gemacht wurde. Da das
hier nicht zutrifft, muss manuell das erledigt werden, was
sonst getbits () macht, d.h. ein Buffer eingelesen werden und
bestimmte Werte in der Struktur gesetzt werden. */
/* The Bitstream package doesn't prepare the buffer when doing
a look_ahead, since it thinks that at least ont getbits ()
function call was done earlier. This gets done by hand here */
bs1.totbit = 32;
bs1.buf_byte_idx = -1;
bs1.buf_bit_idx = 8;
refill_buffer (&bs1);
bs1.buf_byte_idx = bs1.buf_size-1;
bs2.totbit = 32;
bs2.buf_byte_idx = -1;
bs2.buf_bit_idx = 8;
refill_buffer (&bs2);
bs2.buf_byte_idx = bs2.buf_size-1;
*video_file = vfile;
*video_bytes= bytes_1;
//printf ("File %s is a 11172-2 Video stream.\n",vfile);
*ptr_which_streams |= STREAMS_VIDEO;
//printf ("File %s is a 11172-3 Audio stream.\n",afile);
*ptr_which_streams |= STREAMS_AUDIO;
*audio_file = afile;
*audio_bytes= bytes_2;
close_bit_stream_r (&bs1);
close_bit_stream_r (&bs2);
*multi_file = mfile;
}
/*************************************************************************
Get_Info_Video
holt Informationen zu den einzelnen Access-Units (Frames) des
Videofiles ein und speichert sie in einer temporaeren Datei
ab. Wird spaeter zum Aufbau der gemultiplexten Datei gebraucht.
Gets informations on the single access units (frames) of the
video stream and saves them in a tmp file for further
processing. We need it for building the multiplex file.
*************************************************************************/
void get_info_video (video_file, video_units, video_info, startup_delay, length)
char *video_file;
char *video_units;
Video_struc *video_info;
double *startup_delay;
unsigned int length;
{
FILE* info_file;
Bit_stream_struc video_bs;
unsigned int offset_bits=0;
unsigned int stream_length=0;
Vaunit_struc access_unit;
unsigned long syncword;
unsigned long decoding_order=0;
unsigned long group_order=0;
unsigned long temporal_reference=0;
double secs_per_frame=0;
unsigned short pict_rate;
double DTS;
double PTS;
int i;
unsigned int prozent;
unsigned int old_prozent=0;
printf ("scanning Video stream for access units information.\n");
info_file = fopen (video_units, "wb");
open_bit_stream_r (&video_bs, video_file, BUFFER_SIZE);
if (getbits (&video_bs, 32)==SEQUENCE_HEADER)
{
video_info->num_sequence++;
video_info->horizontal_size = getbits (&video_bs, 12);
video_info->vertical_size = getbits (&video_bs, 12);
video_info->aspect_ratio = getbits (&video_bs, 4);
pict_rate = (unsigned short)getbits (&video_bs, 4);
video_info->picture_rate = pict_rate;
video_info->bit_rate = getbits (&video_bs, 18);
marker_bit (&video_bs, 1);
video_info->vbv_buffer_size = getbits (&video_bs, 10);
video_info->CSPF = get1bit (&video_bs);
} else
{
printf ("Invalid MPEG Video stream header.\n");
exit (1);
}
empty_vaunit_struc (&access_unit);
*startup_delay = 2*MAX_FFFFFFFF;
if (pict_rate >0 && pict_rate<9)
secs_per_frame = 1. / picture_rates[pict_rate];
else
secs_per_frame = 1. / 25.; /* invalid pict_rate info */
do {
if (seek_sync (&video_bs, SYNCWORD_START, 24))
{
syncword = (SYNCWORD_START<<8) + getbits (&video_bs, 8);
switch (syncword) {
case SEQUENCE_HEADER:
video_info->num_sequence++;
break;
case GROUP_START:
video_info->num_groups++;
group_order=0;
break;
case PICTURE_START:
/* skip access unit number 0 */
if (access_unit.type != 0)
{
stream_length = sstell (&video_bs)-32;
access_unit.length = (stream_length - offset_bits)>>3;
offset_bits = stream_length;
fwrite (&access_unit, sizeof (Vaunit_struc),
1, info_file);
video_info->avg_frames[access_unit.type-1]+=
access_unit.length;
}
temporal_reference = getbits (&video_bs, 10);
access_unit.type = getbits (&video_bs, 3);
DTS = decoding_order * secs_per_frame*CLOCKS;
PTS = (temporal_reference - group_order + 1 +
decoding_order) * secs_per_frame*CLOCKS;
*startup_delay=(PTS<*startup_delay ? PTS : *startup_delay);
make_timecode (DTS,&access_unit.DTS);
make_timecode (PTS,&access_unit.PTS);
decoding_order++;
group_order++;
if ((access_unit.type>0) && (access_unit.type<5))
video_info->num_frames[access_unit.type-1]++;
prozent =(int) (((float)sstell(&video_bs)/8/(float)length)*100);
video_info->num_pictures++;
if (prozent > old_prozent)
{
printf ("Got %d picture headers. %2d%%\r",
video_info->num_pictures, prozent);
fflush (stdout);
old_prozent = prozent;
}
break;
case SEQUENCE_END:
stream_length = sstell (&video_bs);
access_unit.length = (stream_length - offset_bits)>>3;
fwrite (&access_unit, sizeof (Vaunit_struc),
1, info_file);
video_info->avg_frames[access_unit.type-1]+=
access_unit.length;
offset_bits = stream_length;
video_info->num_seq_end++;
break;
}
} else break;
} while (!end_bs(&video_bs));
//printf ("\nDone, stream bit offset %ld.\n",offset_bits);
video_info->stream_length = offset_bits >> 3;
for (i=0; i<4; i++)
if (video_info->num_frames[i]!=0)
video_info->avg_frames[i] /= video_info->num_frames[i];
if (secs_per_frame >0.)
video_info->comp_bit_rate = (unsigned int)ceil ((double)(video_info->stream_length)/
(double)(video_info->num_pictures)/secs_per_frame/1250.)*25;
else
video_info->comp_bit_rate = 0;
close_bit_stream_r (&video_bs);
fclose (info_file);
//output_info_video (video_info);
//ask_continue ();
}
/*************************************************************************
Output_Info_Video
gibt Ubersicht ueber gesammelte Informationen aus
Prints information on video access units
*************************************************************************/
void output_info_video (video_info)
Video_struc *video_info;
{
printf("\n+------------------ VIDEO STREAM INFORMATION -----------------+\n");
printf ("\nStream length : %8u\n",video_info->stream_length);
printf ("Sequence start : %8u\n",video_info->num_sequence);
printf ("Sequence end : %8u\n",video_info->num_seq_end);
printf ("No. Pictures : %8u\n",video_info->num_pictures);
printf ("No. Groups : %8u\n",video_info->num_groups);
printf ("No. I Frames : %8u avg. size%6u bytes\n",
video_info->num_frames[0],video_info->avg_frames[0]);
printf ("No. P Frames : %8u avg. size%6u bytes\n",
video_info->num_frames[1],video_info->avg_frames[1]);
printf ("No. B Frames : %8u avg. size%6u bytes\n",
video_info->num_frames[2],video_info->avg_frames[2]);
printf ("No. D Frames : %8u avg. size%6u bytes\n",
video_info->num_frames[3],video_info->avg_frames[3]);
printf ("Horizontal size: %8u\n",video_info->horizontal_size);
printf ("Vertical size : %8u\n",video_info->vertical_size);
printf ("Aspect ratio : %1.4f ",ratio[video_info->aspect_ratio]);
switch (video_info->aspect_ratio)
{
case 0: printf ("forbidden\n"); break;
case 1: printf ("VGA etc\n"); break;
case 3: printf ("16:9, 625 line\n"); break;
case 6: printf ("16:9, 525 line\n"); break;
case 8: printf ("CCIR601, 625 line\n"); break;
case 12: printf ("CCIR601, 525 line\n"); break;
case 15: printf ("reserved\n"); break;
default: printf ("\n");
}
if (video_info->picture_rate == 0)
printf("Picture rate : forbidden\n");
else if (video_info->picture_rate <9)
printf("Picture rate : %2.3f frames/sec\n",
picture_rates[video_info->picture_rate]);
else
printf("Picture rate : %x reserved\n",video_info->picture_rate);
if (video_info->bit_rate == 0x3ffff) {
video_info->bit_rate = 0;
printf("Bit rate : variable\n"); }
else if (video_info->bit_rate == 0)
printf("Bit rate : forbidden\n");
else
printf("Bit rate : %8u bytes/sec (%7u bits/sec)\n",
video_info->bit_rate*50,video_info->bit_rate*400);
printf ("Computed rate : %8u bytes/sec\n",video_info->comp_bit_rate*50);
printf ("Vbv buffer size: %8u bytes\n",video_info->vbv_buffer_size*2048);
printf ("CSPF : %8u\n",video_info->CSPF);
}
/*************************************************************************
Output_Info_Audio
gibt gesammelte Informationen zu den Audio Access Units aus.
Prints information on audio access units
*************************************************************************/
void output_info_audio (audio_info)
Audio_struc *audio_info;
{
unsigned int layer;
unsigned long bitrate;
layer=3-audio_info->layer;
bitrate = bitrate_index[layer][audio_info->bit_rate];
printf("\n+------------------ AUDIO STREAM INFORMATION -----------------+\n");
printf ("\nStream length : %8u\n",audio_info->stream_length);
printf ("Syncwords : %8u\n",audio_info->num_syncword);
printf ("Frames : %8u size %6u bytes\n",
audio_info->num_frames[0],audio_info->size_frames[0]);
printf ("Frames : %8u size %6u bytes\n",
audio_info->num_frames[1],audio_info->size_frames[1]);
printf ("Layer : %8u\n",1+layer);
if (audio_info->protection == 0) printf ("CRC checksums : yes\n");
else printf ("CRC checksums : no\n");
if (audio_info->bit_rate == 0)
printf ("Bit rate : free\n");
else if (audio_info->bit_rate == 0xf)
printf ("Bit rate : reserved\n");
else
printf ("Bit rate : %8u bytes/sec (%3u kbit/sec)\n",
bitrate*128, bitrate);
if (audio_info->frequency == 3)
printf ("Frequency : reserved\n");
else
printf ("Frequency : %2.1f kHz\n",
frequency[audio_info->frequency]);
printf ("Mode : %8u %s\n",
audio_info->mode,mode[audio_info->mode]);
printf ("Mode extension : %8u\n",audio_info->mode_extension);
printf ("Copyright bit : %8u %s\n",
audio_info->copyright,copyright[audio_info->copyright]);
printf ("Original/Copy : %8u %s\n",
audio_info->original_copy,original[audio_info->original_copy]);
printf ("Emphasis : %8u %s\n",
audio_info->emphasis,emphasis[audio_info->emphasis]);
}
/*************************************************************************
Get_Info_Audio
holt Informationen zu den einzelnen Audio Access Units
(Audio frames) ein und speichert sie in einer temporaeren
Datei ab.
gets information on the single audio access units (audio frames)
and saves them into a tmp file for further processing.
*************************************************************************/
void get_info_audio (audio_file, audio_units, audio_info, startup_delay, length)
char *audio_file;
char *audio_units;
Audio_struc *audio_info;
double *startup_delay;
unsigned int length;
{
FILE* info_file;
Bit_stream_struc audio_bs;
unsigned int offset_bits=0;
unsigned int stream_length=0;
unsigned int framesize;
unsigned int padding_bit;
unsigned int skip;
unsigned int decoding_order=0;
double PTS;
double samples_per_second;
Aaunit_struc access_unit;
//unsigned long syncword;
unsigned int i;
unsigned int prozent;
unsigned int old_prozent=0;
printf ("\nScanning Audio stream for access units information.\n");
info_file = fopen (audio_units, "wb");
open_bit_stream_r (&audio_bs, audio_file, BUFFER_SIZE);
empty_aaunit_struc (&access_unit);
if (getbits (&audio_bs, 12)==AUDIO_SYNCWORD)
{
marker_bit (&audio_bs, 1);
audio_info->num_syncword++;
audio_info->layer = getbits (&audio_bs, 2);
audio_info->protection = get1bit (&audio_bs);
audio_info->bit_rate = getbits (&audio_bs, 4);
audio_info->frequency = getbits (&audio_bs, 2);
padding_bit=get1bit(&audio_bs);
get1bit (&audio_bs);
audio_info->mode = getbits (&audio_bs, 2);
audio_info->mode_extension = getbits (&audio_bs, 2);
audio_info->copyright = get1bit (&audio_bs);
audio_info->original_copy = get1bit (&audio_bs);
audio_info->emphasis = getbits (&audio_bs, 2);
framesize =
(unsigned int)(bitrate_index[3-audio_info->layer][audio_info->bit_rate] /
frequency[audio_info->frequency] * slots [3-audio_info->layer]);
audio_info->size_frames[0] = framesize;
audio_info->size_frames[1] = framesize+1;
access_unit.length = audio_info->size_frames[padding_bit];
samples_per_second = (double)frequency [audio_info->frequency];
PTS = decoding_order * samples [3-audio_info->layer] /
samples_per_second * 90. + *startup_delay;
make_timecode (PTS, &access_unit.PTS);
decoding_order++;
fwrite (&access_unit, sizeof (Aaunit_struc),1, info_file);
audio_info->num_frames[padding_bit]++;
} else
{
printf ("Invalid MPEG Audio stream header.\n");
exit (1);
}
do {
skip=access_unit.length-4;
if (skip & 0x1) getbits (&audio_bs, 8);
if (skip & 0x2) getbits (&audio_bs, 16);
skip=skip>>2;
for (i=0;inum_syncword++;
if (prozent > old_prozent)
{
printf ("Got %d frame headers. %2d%%\r",
audio_info->num_syncword,prozent);
fflush (stdout);
old_prozent=prozent;
}
getbits (&audio_bs, 9);
padding_bit=get1bit(&audio_bs);
access_unit.length = audio_info->size_frames[padding_bit];
PTS = decoding_order * samples [3-audio_info->layer] /
samples_per_second * 90. + *startup_delay;
make_timecode (PTS, &access_unit.PTS);
decoding_order++;
fwrite (&access_unit, sizeof (Aaunit_struc),1, info_file);
audio_info->num_frames[padding_bit]++;
getbits (&audio_bs, 9);
}
else break;
} while (!end_bs(&audio_bs));
//printf ("\nDone, stream bit offset %ld.\n",offset_bits);
audio_info->stream_length = offset_bits >> 3;
close_bit_stream_r (&audio_bs);
fclose (info_file);
//output_info_audio (audio_info);
//ask_continue ();
}