Integrated and used Cyrius's AVI classes.

This commit is contained in:
Moritz Bunkus 2003-10-05 15:22:24 +00:00
parent 0b06d2a3b5
commit b4b9376ee9
14 changed files with 357 additions and 106 deletions

View File

@ -19,6 +19,14 @@ DIE=0
DIE=1
}
(autoheader --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoheader installed to compile $package."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have automake installed to compile $package."
@ -55,7 +63,7 @@ esac
echo "Generating configuration files for $package, please wait...."
echo " aclocal $ACLOCAL_FLAGS" && aclocal $ACLOCAL_FLAGS
#echo " autoheader" && autoheader
echo " autoheader" && autoheader
#echo " libtoolize --automake" && libtoolize --automake
echo " autoconf" && autoconf
echo " automake --add-missing --copy" && automake --add-missing --copy

View File

@ -23,6 +23,7 @@
#ifndef f_AVIINDEX_H
#define f_AVIINDEX_H
#include "common_endian.h"
#include "common_gdivfw.h"
class AVIIndexChainNode;

View File

@ -2,6 +2,6 @@ DEFAULT_INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I.
noinst_LIBRARIES = libaviclasses.a
libaviclasses_a_SOURCES = AVIIndex.cpp \
AVIReadHandler.cpp \
libaviclasses_a_SOURCES = AVIReadHandler.cpp \
AVIIndex.cpp \
list.cpp

View File

@ -26,7 +26,7 @@
#define LIL_ENDIAN 0x0102
#define BIG_ENDIAN 0x0201
#ifdef WORDS_BIGENDIAN
#if WORDS_BIGENDIAN == 1
# define AVI_BYTE_ORDER BIG_ENDIAN
#else
# define AVI_BYTE_ORDER LIL_ENDIAN
@ -38,7 +38,7 @@ typedef enum {
} eEndianness;
template<class _T, eEndianness _ENDIANNESS>
class TOOLS_DLL_API EndianValue {
class EndianValue {
protected:
_T m_Value;

View File

@ -305,10 +305,10 @@ typedef struct {
#define bitmapFOURCC mmioFOURCC
inline bool isValidFOURCC(uint32 fcc) {
return isalpha(uint8(fcc>>24))
&& isalpha(uint8(fcc>>16))
&& isalpha(uint8(fcc>> 8))
&& isalpha(uint8(fcc ));
return isprint(uint8(fcc>>24))
&& isprint(uint8(fcc>>16))
&& isprint(uint8(fcc>> 8))
&& isprint(uint8(fcc ));
}
/* form types, list types, and chunk types */

View File

@ -4,6 +4,7 @@ AC_INIT(src/mkvmerge.cpp)
AC_PREREQ(2.50)
AM_INIT_AUTOMAKE(mkvtoolnix,0.7.1)
AM_CONFIG_HEADER(config.h)
AC_PROG_CC
AC_PROG_CC_C_O
@ -612,13 +613,13 @@ dnl
dnl Check for libexpat
dnl
AC_ARG_WITH(expat-prefix,
[ --with-expat-prefix=PFX Path to where the Expat library is installed],,
[ --with-expat-prefix=PFX Path to where the Expat library is installed],,
with_expat_given=no)
AC_ARG_WITH(expat-includes,
[ --with-expat-includes=DIR Path to the Expat include file],,
[ --with-expat-includes=DIR Path to the Expat include file],,
with_expat_includes_given=no)
AC_ARG_WITH(expat-libraries,
[ --with-expat-libraries=DIR Path to where the Expat library is installed],,
[ --with-expat-libraries=DIR Path to where the Expat library is installed],,
with_expat_libraries_given=no)
EXPAT_CFLAGS=
@ -662,7 +663,7 @@ dnl
dnl Check for zlib
dnl
AC_ARG_WITH(zlib,
[ --with-zlib-prefix=PFX Path to where the zlib library is installed],,
[ --with-zlib-prefix=PFX Path to where the zlib library is installed],,
with_zlib_given=no)
ZLIB_CFLAGS=
@ -694,7 +695,7 @@ dnl
dnl Check for liblzo
dnl
AC_ARG_WITH(lzo,
[ --with-lzo-prefix=PFX Path to where the lzo library is installed],,
[ --with-lzo-prefix=PFX Path to where the lzo library is installed],,
with_lzo_given=no)
LZO_CFLAGS=
@ -726,7 +727,7 @@ dnl
dnl Check for libbz2
dnl
AC_ARG_WITH(bz2,
[ --with-bz2-prefix=PFX Path to where the bz2 library is installed],,
[ --with-bz2-prefix=PFX Path to where the bz2 library is installed],,
with_bz2_given=no)
BZ2_CFLAGS=
@ -784,14 +785,13 @@ dnl
WXWINDOWS_LDFLAGS=$(wx-config --ldflags)
WXWINDOWS_LIBS=$(wx-config --libs)
fi
echo '#define HAVE_WXWINDOWS 1' >> config.h
AC_DEFINE(HAVE_WXWINDOWS, 1, [Define if wxWindows is present])
AC_MSG_RESULT($wxwversion ok)
have_wxwindows=yes
else
AC_MSG_RESULT(no: version $wxwversion is too old)
fi
else
echo '/* #define HAVE_WXWINDOWS 1 */' >> config.h
AC_MSG_RESULT(no: wx-config was not found)
fi
@ -800,19 +800,28 @@ AC_SUBST(WXWINDOWS_LDFLAGS)
AC_SUBST(WXWINDOWS_LIBS)
AM_CONDITIONAL(HAVE_WXWINDOWS, test x"$have_wxwindows" = "xyes")
AVILIB_CFLAGS="-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
AVILIB_LIBS="-lavi"
AVICLASSES_CXXFLAGS="-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
AVICLASSES_LIBS="-laviclasses"
dnl
dnl Option to use the (old) avilib library instead of the AVI classes
dnl
AC_ARG_ENABLE(avilib,
[ --enable-avilib Use avilib instead of AVIclasses],
have_aviclasses=no, have_aviclasses=yes)
if test "x$have_aviclasses" = "xyes"; then
AC_DEFINE(HAVE_AVICLASSES, 1,
[Define if the newer AVIclasses should be used])
fi
AVILIB_LIBS="-lavi"
AVICLASSES_LIBS="-laviclasses"
AC_SUBST(AVILIB_CFLAGS)
AC_SUBST(AVILIB_LIBS)
AC_SUBST(AVICLASSES_CXXFLAGS)
AC_SUBST(AVICLASSES_LIBS)
CFLAGS="-Wall -Wno-sign-compare -Wno-comment @EXTRA_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@ @AVILIB_CFLAGS@ @DEBUG_CFLAGS@ @PROFILING_CFLAGS@ @MATROSKA_CFLAGS@ @EBML_CFLAGS@"
CXXFLAGS="-Wall -Wno-sign-compare -Wno-comment @EXTRA_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@ @AVILIB_CFLAGS@ @AVICLASSES_CXXFLAGS@ @DEBUG_CFLAGS@ @PROFILING_CFLAGS@ @MATROSKA_CFLAGS@ @EBML_CFLAGS@ @WXWINDOWS_CFLAGS@ @EXPAT_CFLAGS@ @ZLIB_CFLAGS@ @LZO_CFLAGS@ @BZ2_CFLAGS@"
CFLAGS="-Wall -Wno-sign-compare -Wno-comment -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 @EXTRA_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@ @DEBUG_CFLAGS@ @PROFILING_CFLAGS@ @MATROSKA_CFLAGS@ @EBML_CFLAGS@"
CXXFLAGS="-Wall -Wno-sign-compare -Wno-comment -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 @EXTRA_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@ @DEBUG_CFLAGS@ @PROFILING_CFLAGS@ @MATROSKA_CFLAGS@ @EBML_CFLAGS@ @WXWINDOWS_CFLAGS@ @EXPAT_CFLAGS@ @ZLIB_CFLAGS@ @LZO_CFLAGS@ @BZ2_CFLAGS@"
CPPFLAGS="@EXTRA_CFLAGS@"
LDFLAGS="@EXTRA_LDFLAGS@"

View File

@ -77,9 +77,7 @@
#include "r_dts.h"
#include "r_matroska.h"
#include "r_mp3.h"
#ifdef HAVE_OGGVORBIS
#include "r_ogm.h"
#endif
#include "r_qtmp4.h"
#include "r_real.h"
#include "r_srt.h"
@ -219,9 +217,7 @@ file_type_t file_types[] =
{"mp2", TYPEMP3, "MPEG1 layer II audio (CBR and VBR/ABR)"},
{"mp3", TYPEMP3, "MPEG1 layer III audio (CBR and VBR/ABR)"},
{"mkv", TYPEMATROSKA, "general Matroska files"},
#ifdef HAVE_OGGVORBIS
{"ogg", TYPEOGM, "general OGG media stream, audio/video embedded in OGG"},
#endif // HAVE_OGGVORBIS
{"mov", TYPEQTMP4, "Quicktime/MP4 audio and video"},
{"rm ", TYPEREAL, "RealMedia audio and video"},
{"srt", TYPESRT, "SRT text subtitles"},
@ -236,9 +232,7 @@ file_type_t file_types[] =
{" ", -1, "simple text subtitles"},
{" ", -1, "uncompressed PCM audio"},
{" ", -1, "Video (not MPEG1/2)"},
#ifdef HAVE_OGGVORBIS
{" ", -1, "Vorbis audio"},
#endif // HAVE_OGGVORBIS
{NULL, -1, NULL}};
// }}}
@ -371,10 +365,8 @@ static int get_type(char *filename) {
type = TYPEMATROSKA;
else if (wav_reader_c::probe_file(mm_io, size))
type = TYPEWAV;
#ifdef HAVE_OGGVORBIS
else if (ogm_reader_c::probe_file(mm_io, size))
type = TYPEOGM;
#endif // HAVE_OGGVORBIS
else if (real_reader_c::probe_file(mm_io, size))
type = TYPEREAL;
else if (qtmp4_reader_c::probe_file(mm_io, size))
@ -986,11 +978,9 @@ static void create_readers() {
case TYPEMATROSKA:
file->reader = new kax_reader_c(file->ti);
break;
#ifdef HAVE_OGGVORBIS
case TYPEOGM:
file->reader = new ogm_reader_c(file->ti);
break;
#endif // HAVE_OGGVORBIS
case TYPEAVI:
file->reader = new avi_reader_c(file->ti);
break;

View File

@ -1,6 +1,8 @@
#ifndef __OS_H
#define __OS_H
#include "config.h"
#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
# define SYS_WINDOWS
# if defined __MINGW32__

View File

@ -20,8 +20,6 @@
#include "config.h"
#ifdef HAVE_OGGVORBIS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -206,5 +204,3 @@ int vorbis_packetizer_c::process(unsigned char *data, int size,
void vorbis_packetizer_c::dump_debug_info() {
mxdebug("vorbis_packetizer_c: queue: %d\n", packet_queue.size());
}
#endif // HAVE_OGGVORBIS

View File

@ -20,8 +20,6 @@
#include "config.h"
#ifdef HAVE_OGGVORBIS
#ifndef __P_VORBIS_H
#define __P_VORBIS_H
@ -58,5 +56,3 @@ public:
};
#endif // __P_VORBIS_H
#endif // HAVE_OGGVORBIS

View File

@ -20,14 +20,22 @@
// {{{ includes
#include "os.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_AVICLASSES
#include "common_mmreg.h"
#include "common_gdivfw.h"
#include "AVIReadHandler.h"
#else
extern "C" {
#include <avilib.h>
}
#endif
#include "mkvmerge.h"
#include "common.h"
@ -38,6 +46,9 @@ extern "C" {
#include "p_mp3.h"
#include "p_ac3.h"
#define PFX "avi_reader: "
#define MIN_CHUNK_SIZE 128000
// }}}
// {{{ FUNCTION avi_reader_c::probe_file
@ -67,42 +78,132 @@ int avi_reader_c::probe_file(mm_io_c *mm_io, int64_t size) {
avi_reader_c::avi_reader_c(track_info_t *nti) throw (error_c):
generic_reader_c(nti) {
int fsize, i;
long fsize, i;
int64_t size, bps;
mm_io_c *mm_io;
avi_demuxer_t *demuxer;
#ifdef HAVE_AVICLASSES
w32AVISTREAMINFO stream_info;
long format_size;
w32BITMAPINFOHEADER *bih;
char codec[5];
#else
char *codec;
#endif
try {
mm_io = new mm_io_c(ti->fname, MODE_READ);
mm_io->setFilePointer(0, seek_end);
size = mm_io->getFilePointer();
mm_io->setFilePointer(0, seek_beginning);
if (!avi_reader_c::probe_file(mm_io, size))
throw error_c("avi_reader: Source is not a valid AVI file.");
delete mm_io;
io = new mm_io_c(ti->fname, MODE_READ);
size = io->get_size();
if (!avi_reader_c::probe_file(io, size))
throw error_c(PFX "Source is not a valid AVI file.");
} catch (exception &ex) {
throw error_c("avi_reader: Could not read the source file.");
throw error_c(PFX "Could not read the source file.");
}
if (verbose)
mxinfo("Using AVI demultiplexer for %s. Opening file. This "
"may take some time depending on the file's size.\n", ti->fname);
fsize = 0;
rederive_keyframes = 0;
#ifdef HAVE_AVICLASSES
avi = CreateAVIReadHandler(io);
if (avi == NULL)
throw error_c(PFX "Could not initialize the AVI handler.");
s_video = avi->GetStream(streamtypeVIDEO, 0);
if (s_video == NULL)
throw error_c(PFX "No video stream found in file.");
mxverb(2, "1: 0x%08x\n", s_video);
if (s_video->Info(&stream_info, sizeof(stream_info)) != S_OK)
throw error_c(PFX "Could not get the video stream information.");
s_video->FormatSize(0, &format_size);
mxverb(2, "2: format_size %ld\n", format_size);
bih = (w32BITMAPINFOHEADER *)safemalloc(format_size);
if (s_video->ReadFormat(0, bih, &format_size) != S_OK)
throw error_c(PFX "Could not read the video format information.");
frames = s_video->Start();
maxframes = s_video->End();
mxverb(2, "3: maxframes %ld\n", maxframes);
fps = (float)stream_info.dwRate / (float)stream_info.dwScale;
mxverb(2, "4: fps %.3f\n", fps);
max_frame_size = 0;
for (i = 0; i < maxframes; i++) {
if (s_video->Read(i, 1, NULL, 0, &fsize, NULL) != S_OK)
break;
if (fsize > max_frame_size)
max_frame_size = fsize;
}
mxverb(2, "5: max_frame_size %d\n", max_frame_size);
if (demuxing_requested('v', 0)) {
memcpy(codec, &bih->biCompression, 4);
codec[4] = 0;
if (!strcasecmp(codec, "DIV3") ||
!strcasecmp(codec, "AP41") || // Angel Potion
!strcasecmp(codec, "MPG3") ||
!strcasecmp(codec, "MP43"))
is_divx = RAVI_DIVX3;
else if (!strcasecmp(codec, "MP42") ||
!strcasecmp(codec, "DIV2") ||
!strcasecmp(codec, "DIVX") ||
!strcasecmp(codec, "XVID") ||
!strcasecmp(codec, "DX50"))
is_divx = RAVI_MPEG4;
else
is_divx = 0;
ti->private_data = (unsigned char *)bih;
if (ti->private_data != NULL)
ti->private_size = bih->biSize;
if (ti->fourcc[0] == 0) {
memcpy(ti->fourcc, codec, 4);
ti->fourcc[4] = 0;
} else
memcpy(&bih->biCompression, ti->fourcc, 4);
ti->id = 0; // ID for the video track.
vpacketizer = new video_packetizer_c(this, NULL, fps,
bih->biWidth, bih->biHeight,
false, ti);
if (verbose)
mxinfo("+-> Using video output module for video track ID 0.\n");
mxverb(2, "6: width %u, height %u\n", bih->biWidth, bih->biHeight);
} else
vpacketizer = NULL;
safefree(bih);
i = 0;
while (true) {
if (avi->GetStream(streamtypeAUDIO, i) == NULL)
break;
if (demuxing_requested('a', i + 1))
add_audio_demuxer(i);
i++;
}
for (i = 0; i < ademuxers.size(); i++) {
demuxer = ademuxers[i];
bps = demuxer->samples_per_second * demuxer->channels *
demuxer->bits_per_sample / 8;
if (bps > max_frame_size)
max_frame_size = bps;
}
#else
frames = 0;
delete io;
if ((avi = AVI_open_input_file(ti->fname, 1)) == NULL) {
const char *msg = "avi_reader: Could not initialize AVI source. Reason: ";
const char *msg = PFX "Could not initialize AVI source. Reason: ";
char *s, *error;
error = AVI_strerror();
s = (char *)safemalloc(strlen(msg) + strlen(error) + 1);
mxprints(s, "%s%s", msg, error);
throw error_c(s);
throw error_c(s, true);
}
fps = AVI_frame_rate(avi);
if (video_fps < 0)
video_fps = fps;
frames = 0;
fsize = 0;
maxframes = AVI_video_frames(avi);
for (i = 0; i < maxframes; i++)
if (AVI_frame_size(avi, i) > fsize)
@ -144,7 +245,7 @@ avi_reader_c::avi_reader_c(track_info_t *nti) throw (error_c):
for (i = 0; i < AVI_audio_tracks(avi); i++)
if (demuxing_requested('a', i + 1))
add_audio_demuxer(avi, i);
add_audio_demuxer(i);
for (i = 0; i < ademuxers.size(); i++) {
demuxer = ademuxers[i];
@ -153,8 +254,12 @@ avi_reader_c::avi_reader_c(track_info_t *nti) throw (error_c):
if (bps > fsize)
fsize = bps;
}
max_frame_size = fsize;
chunk = (unsigned char *)safemalloc(fsize < 16384 ? 16384 : fsize);
#endif
if (video_fps < 0)
video_fps = fps;
chunk = (unsigned char *)safemalloc(max_frame_size < MIN_CHUNK_SIZE ?
MIN_CHUNK_SIZE : max_frame_size);
act_wchar = 0;
old_key = 0;
old_chunk = NULL;
@ -170,8 +275,13 @@ avi_reader_c::~avi_reader_c() {
avi_demuxer_t *demuxer;
int i;
#ifdef HAVE_AVICLASSES
avi->Release();
delete io;
#else
if (avi != NULL)
AVI_close(avi);
#endif
if (chunk != NULL)
safefree(chunk);
if (vpacketizer != NULL)
@ -198,34 +308,76 @@ avi_reader_c::~avi_reader_c() {
// {{{ FUNCTION avi_reader_c::add_audio_demuxer
void avi_reader_c::add_audio_demuxer(avi_t *avi, int aid) {
void avi_reader_c::add_audio_demuxer(int aid) {
avi_demuxer_t *demuxer;
alWAVEFORMATEX *wfe;
int i;
#ifdef HAVE_AVICLASSES
w32AVISTREAMINFO stream_info;
long format_size;
// w32WAVEFORMATEX *wfe;
w32WAVEFORMATEX *wfe;
IAVIReadStream *stream;
#else
alWAVEFORMATEX *wfe;
#endif
uint32_t audio_format;
for (i = 0; i < ademuxers.size(); i++)
if (ademuxers[i]->aid == aid) // Demuxer already added?
return;
AVI_set_audio_track(avi, aid);
demuxer = (avi_demuxer_t *)safemalloc(sizeof(avi_demuxer_t));
memset(demuxer, 0, sizeof(avi_demuxer_t));
demuxer->aid = aid;
wfe = avi->wave_format_ex[aid];
ti->private_data = (unsigned char *)wfe;
if (wfe != NULL)
ti->private_size = wfe->cb_size + sizeof(alWAVEFORMATEX);
else
ti->private_size = 0;
ti->id = aid + 1; // ID for this audio track.
switch (AVI_audio_format(avi)) {
#ifdef HAVE_AVICLASSES
stream = avi->GetStream(streamtypeAUDIO, aid);
if (stream == NULL)
die(PFX "stream == NULL in add_audio_demuxer. Should not have happened. "
"Please file a bug report.\n");
demuxer->stream = stream;
if (stream->Info(&stream_info, sizeof(w32AVISTREAMINFO)) != S_OK)
mxerror(PFX "Could not read the stream information header for audio track "
"%d.\n", aid + 1);
stream->FormatSize(0, &format_size);
wfe = (w32WAVEFORMATEX *)safemalloc(format_size);
if (stream->ReadFormat(0, wfe, &format_size) != S_OK)
mxerror(PFX "Could not read the format information header for audio track "
"%d.\n", aid + 1);
audio_format = wfe->wFormatTag;
demuxer->samples_per_second = wfe->nSamplesPerSec;
demuxer->channels = wfe->nChannels;
demuxer->bits_per_sample = wfe->wBitsPerSample;
demuxer->frame = stream->Start();
demuxer->maxframes = stream->End();
mxverb(2, "7: sizeof(w32WAVE...) %d, sps %d, c %d, bps %d, mf %d\n",
sizeof(w32WAVEFORMATEX), demuxer->samples_per_second,
demuxer->channels, demuxer->bits_per_sample, demuxer->maxframes);
#else
wfe = avi->wave_format_ex[aid];
AVI_set_audio_track(avi, aid);
audio_format = AVI_audio_format(avi);
demuxer->samples_per_second = AVI_audio_rate(avi);
demuxer->channels = AVI_audio_channels(avi);
demuxer->bits_per_sample = AVI_audio_bits(avi);
#endif
if (wfe->cbSize > 0) {
ti->private_data = (unsigned char *)(wfe + 1);
ti->private_size = wfe->cbSize;
} else {
ti->private_data = NULL;
ti->private_size = 0;
}
switch(audio_format) {
case 0x0001: // raw PCM audio
if (verbose)
mxinfo("+-> Using PCM output module for audio track ID %d.\n",
aid + 1);
demuxer->samples_per_second = AVI_audio_rate(avi);
demuxer->channels = AVI_audio_channels(avi);
demuxer->bits_per_sample = AVI_audio_bits(avi);
demuxer->packetizer = new pcm_packetizer_c(this,
demuxer->samples_per_second,
demuxer->channels,
@ -235,9 +387,6 @@ void avi_reader_c::add_audio_demuxer(avi_t *avi, int aid) {
if (verbose)
mxinfo("+-> Using MPEG audio output module for audio track ID %d.\n",
aid + 1);
demuxer->samples_per_second = AVI_audio_rate(avi);
demuxer->channels = AVI_audio_channels(avi);
demuxer->bits_per_sample = AVI_audio_mp3rate(avi);
demuxer->packetizer = new mp3_packetizer_c(this,
demuxer->samples_per_second,
demuxer->channels, 3, ti);
@ -246,19 +395,20 @@ void avi_reader_c::add_audio_demuxer(avi_t *avi, int aid) {
if (verbose)
mxinfo("+-> Using AC3 output module for audio track ID %d.\n",
aid + 1);
demuxer->samples_per_second = AVI_audio_rate(avi);
demuxer->channels = AVI_audio_channels(avi);
demuxer->bits_per_sample = AVI_audio_mp3rate(avi);
demuxer->packetizer = new ac3_packetizer_c(this,
demuxer->samples_per_second,
demuxer->channels, 0, ti);
break;
default:
mxerror("Unknown audio format 0x%04x for audio track ID %d.\n",
AVI_audio_format(avi), aid + 1);
audio_format, aid + 1);
return;
}
#ifdef HAVE_AVICLASSES
safefree(wfe);
#endif
ademuxers.push_back(demuxer);
}
@ -298,11 +448,17 @@ int avi_reader_c::is_keyframe(unsigned char *data, long size, int suggestion) {
// {{{ FUNCTION avi_reader_c::read
int avi_reader_c::read(generic_packetizer_c *ptzr) {
int nread, key, last_frame, i;
int key, last_frame, i, frames_read;
long nread;
avi_demuxer_t *demuxer;
bool need_more_data, done;
int frames_read, size;
int64_t duration;
#ifdef HAVE_AVICLASSES
long blread;
int result;
#else
int size;
#endif
if ((vpacketizer != NULL) && !video_done && (vpacketizer == ptzr)) {
debug_enter("avi_reader_c::read (video)");
@ -313,9 +469,18 @@ int avi_reader_c::read(generic_packetizer_c *ptzr) {
// Make sure we have a frame to work with.
if (old_chunk == NULL) {
#ifdef HAVE_AVICLASSES
debug_enter("aviclasses->Read() video");
key = s_video->IsKeyFrame(frames);
if (s_video->Read(frames, 1, chunk, 0x7FFFFFFF, &nread, &blread) !=
AVIERR_OK)
nread = -1;
debug_leave("aviclasses->Read() video");
#else
debug_enter("AVI_read_frame");
nread = AVI_read_frame(avi, (char *)chunk, &key);
debug_leave("AVI_read_frame");
#endif
if (nread < 0) {
frames = maxframes + 1;
done = true;
@ -331,13 +496,22 @@ int avi_reader_c::read(generic_packetizer_c *ptzr) {
frames_read = 1;
// Check whether we have identical frames
while (!done && (frames <= (maxframes - 1))) {
#ifdef HAVE_AVICLASSES
debug_enter("aviclasses->Read() video");
key = s_video->IsKeyFrame(frames);
if (s_video->Read(frames, 1, chunk, 0x7FFFFFFF, &nread, &blread) !=
AVIERR_OK)
nread = -1;
debug_leave("aviclasses->Read() video");
#else
debug_enter("AVI_read_frame");
nread = AVI_read_frame(avi, (char *)chunk, &key);
debug_leave("AVI_read_frame");
#endif
if (nread < 0) {
vpacketizer->process(old_chunk, old_nread, -1, -1,
old_key ? VFT_IFRAME : VFT_PFRAMEAUTOMATIC);
mxwarn("avi_reader: Reading frame number %d resulted in an error. "
mxwarn(PFX "Reading frame number %d resulted in an error. "
"Aborting this track.\n", frames);
frames = maxframes + 1;
break;
@ -395,25 +569,37 @@ int avi_reader_c::read(generic_packetizer_c *ptzr) {
debug_enter("avi_reader_c::read (audio)");
need_more_data = false;
#ifdef HAVE_AVICLASSES
if (demuxer->frame < demuxer->maxframes) {
debug_enter("aviclasses->Read() audio");
result = demuxer->stream->Read(demuxer->frame, AVISTREAMREAD_CONVENIENT,
chunk, max_frame_size, &nread, &blread);
debug_leave("aviclasses->Read() audio");
demuxer->frame += blread;
if (result == S_OK) {
demuxer->packetizer->process(chunk, nread);
need_more_data = demuxer->frame < demuxer->maxframes;
} else
demuxer->frame = demuxer->maxframes;
}
#else
AVI_set_audio_track(avi, demuxer->aid);
if (AVI_audio_format(avi) == 0x0001)
size = demuxer->channels * demuxer->bits_per_sample *
demuxer->samples_per_second / 8;
else
size = 16384;
size = MIN_CHUNK_SIZE;
debug_enter("AVI_read_audio");
nread = AVI_read_audio(avi, (char *)chunk, size);
debug_leave("AVI_read_audio");
if (nread > 0) {
if (nread < size)
demuxer->eos = 1;
else
demuxer->eos = 0;
if (nread > size)
need_more_data = true;
demuxer->packetizer->process(chunk, nread);
}
if (!demuxer->eos)
need_more_data = true;
#endif
debug_leave("avi_reader_c::read (audio)");
@ -447,11 +633,10 @@ void avi_reader_c::display_progress(bool final) {
if (frames == (maxframes + 1))
myframes--;
if (final)
mxinfo("progress: %ld/%ld frames (100%%)\r", AVI_video_frames(avi),
AVI_video_frames(avi));
mxinfo("progress: %ld/%ld frames (100%%)\r", maxframes, maxframes);
else
mxinfo("progress: %d/%ld frames (%ld%%)\r", myframes,
AVI_video_frames(avi), myframes * 100 / AVI_video_frames(avi));
mxinfo("progress: %d/%ld frames (%ld%%)\r", myframes, maxframes,
myframes * 100 / maxframes);
} else {
mxinfo("Working... %c\r", wchar[act_wchar]);
act_wchar++;
@ -481,9 +666,62 @@ void avi_reader_c::set_headers() {
void avi_reader_c::identify() {
int i;
const char *type;
#ifdef HAVE_AVICLASSES
w32AVISTREAMINFO stream_info;
w32BITMAPINFOHEADER *bih;
w32WAVEFORMATEX *wfe;
IAVIReadStream *stream;
long format_size;
char codec[5];
#endif
mxinfo("File '%s': container: AVI\n", ti->fname);
#ifdef HAVE_AVICLASSES
stream = avi->GetStream(streamtypeVIDEO, 0);
if (stream->Info(&stream_info, sizeof(stream_info)) != S_OK)
mxerror(PFX "Could not get the video stream information.");
stream->FormatSize(0, &format_size);
mxverb(2, "2: format_size %ld\n", format_size);
bih = (w32BITMAPINFOHEADER *)safemalloc(format_size);
if (stream->ReadFormat(0, bih, &format_size) != S_OK)
mxerror(PFX "Could not read the video format information.");
memcpy(codec, &bih->biCompression, 4);
safefree(bih);
codec[4] = 0;
mxinfo("Track ID 0: video (%s)\n", codec);
mxinfo("File '%s': container: AVI\nTrack ID 0: video (%s)\n",
ti->fname, AVI_video_compressor(avi));
i = 0;
while (true) {
stream = avi->GetStream(streamtypeAUDIO, i);
if (stream == NULL)
break;
if (stream->Info(&stream_info, sizeof(w32AVISTREAMINFO)) != S_OK)
mxerror(PFX "Could not read the stream information header for audio "
"track %d.\n", i + 1);
stream->FormatSize(0, &format_size);
wfe = (w32WAVEFORMATEX *)safemalloc(format_size);
if (stream->ReadFormat(0, wfe, &format_size) != S_OK)
mxerror(PFX "Could not read the format information header for audio "
"track %d.\n", i + 1);
switch (wfe->wFormatTag) {
case 0x0001:
type = "PCM";
break;
case 0x0055:
type = "MP3";
break;
case 0x2000:
type = "AC3";
break;
default:
type = "unknown";
}
mxinfo("Track ID %d: audio (%s)\n", i + 1, type);
safefree(wfe);
i++;
}
#else
mxinfo("Track ID 0: video (%s)\n", AVI_video_compressor(avi));
for (i = 0; i < AVI_audio_tracks(avi); i++) {
AVI_set_audio_track(avi, i);
switch (AVI_audio_format(avi)) {
@ -501,6 +739,7 @@ void avi_reader_c::identify() {
}
mxinfo("Track ID %d: audio (%s)\n", i + 1, type);
}
#endif
}
// }}}

View File

@ -27,9 +27,13 @@
#include <vector>
#ifdef HAVE_AVICLASSES
#include <AVIReadHandler.h>
#else
extern "C" {
#include <avilib.h>
}
#endif
#include "mm_io.h"
#include "pr_generic.h"
@ -43,16 +47,24 @@ extern "C" {
typedef struct avi_demuxer_t {
generic_packetizer_c *packetizer;
int channels, bits_per_sample, samples_per_second;
int aid;
int eos;
int channels, bits_per_sample, samples_per_second, aid;
int64_t bytes_processed;
#ifdef HAVE_AVICLASSES
IAVIReadStream *stream;
int frame, maxframes;
#endif
} avi_demuxer_t;
class avi_reader_c: public generic_reader_c {
private:
unsigned char *chunk, *old_chunk;
#ifdef HAVE_AVICLASSES
IAVIReadHandler *avi;
IAVIReadStream *s_video;
#else
avi_t *avi;
#endif
mm_io_c *io;
video_packetizer_c *vpacketizer;
vector<avi_demuxer_t *> ademuxers;
double fps;
@ -72,7 +84,7 @@ public:
static int probe_file(mm_io_c *mm_io, int64_t size);
private:
virtual void add_audio_demuxer(avi_t *avi, int aid);
virtual void add_audio_demuxer(int aid);
virtual int is_keyframe(unsigned char *data, long size, int suggestion);
};

View File

@ -20,8 +20,6 @@
#include "config.h"
#ifdef HAVE_OGGVORBIS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -751,5 +749,3 @@ void ogm_reader_c::identify() {
"unknown");
}
}
#endif // HAVE_OGGVORBIS

View File

@ -21,6 +21,8 @@
// A lot of code in this file is from the mplayer sources. The original
// authors are to be thanked for their work.
#include "os.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>