mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2025-01-24 10:51:26 +00:00
Integrated and used Cyrius's AVI classes.
This commit is contained in:
parent
0b06d2a3b5
commit
b4b9376ee9
10
autogen.sh
10
autogen.sh
@ -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
|
||||
|
@ -23,6 +23,7 @@
|
||||
#ifndef f_AVIINDEX_H
|
||||
#define f_AVIINDEX_H
|
||||
|
||||
#include "common_endian.h"
|
||||
#include "common_gdivfw.h"
|
||||
|
||||
class AVIIndexChainNode;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
41
configure.in
41
configure.in
@ -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@"
|
||||
|
||||
|
@ -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;
|
||||
|
2
src/os.h
2
src/os.h
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
349
src/r_avi.cpp
349
src/r_avi.cpp
@ -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
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
20
src/r_avi.h
20
src/r_avi.h
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user