commit e3853cddfbcc012cf4433eef9f2d3901c4bc7188
parent 96fb8d67c9f0dc70101a34c862532528c9ec0076
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 17 May 2006 08:25:00 +0000
fixing mantis 826
Diffstat:
5 files changed, 88 insertions(+), 136 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -1,3 +1,7 @@
+Wed May 17 02:05:37 PDT 2006
+ Switched mpegextractor to use libmpeg2 (improves correctness,
+ adds dependency!).
+
Tue May 16 20:08:30 PDT 2006
Dramatically improved qt extractor (essentially re-written from
scratch).
diff --git a/README.debian b/README.debian
@@ -15,6 +15,7 @@ libvorbis-dev
zlib1g-dev
libbz2-dev
libgsf-1-dev
+libmpeg2-4-dev
For Subversion access and compilation:
diff --git a/configure.ac b/configure.ac
@@ -152,6 +152,11 @@ AC_CHECK_LIB(bz2, BZ2_decompress,
AC_DEFINE(HAVE_LIBBZ2,1,[Have libbz2])],
[AM_CONDITIONAL(HAVE_BZ2, false)])
+AC_CHECK_LIB(mpeg2, mpeg2_init,
+ [AM_CONDITIONAL(HAVE_MPEG2, true)
+ AC_DEFINE(HAVE_LIBMPEG2,1,[Have libmpeg2])],
+ [AM_CONDITIONAL(HAVE_MPEG2, false)])
+
# restore LIBS
LIBS=$LIBSOLD
@@ -176,7 +181,7 @@ AC_HEADER_STDC
AC_HEADER_DIRENT
AC_HEADER_STDBOOL
AC_CHECK_HEADERS([fcntl.h netinet/in.h stdlib.h string.h unistd.h libintl.h limits.h stddef.h zlib.h])
-AC_CHECK_HEADERS([ltdl.h iconv.h bzlib.h])
+AC_CHECK_HEADERS([ltdl.h iconv.h bzlib.h mpeg2dec/mpeg2.h])
# fixme, we need to die here if a header is not found!
AC_CHECK_HEADERS([vorbis/vorbisfile.h])
@@ -367,3 +372,8 @@ if test "x$HAVE_ZLIB_TRUE" = "x#"
then
AC_MSG_ERROR([FATAL: zlib not found (headers not installed?)])
fi
+
+if test "x$HAVE_MPEG2_TRUE" = "x#"
+then
+ AC_MSG_ERROR([FATAL: libmpeg2 not found])
+fi
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
@@ -230,7 +230,7 @@ libextractor_mpeg_la_LDFLAGS = \
$(top_builddir)/src/main/libextractor.la \
$(PLUGINFLAGS) $(retaincommand)
libextractor_mpeg_la_LIBADD = \
- -lm
+ -lmpeg2
libextractor_man_la_SOURCES = \
manextractor.c
diff --git a/src/plugins/mpegextractor.c b/src/plugins/mpegextractor.c
@@ -1,7 +1,7 @@
/*
This file is part of libextractor.
- (C) 2004, 2005 Vidyut Samanta and Christian Grothoff
+ (C) 2004, 2005, 2006 Vidyut Samanta and Christian Grothoff
libextractor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -17,20 +17,11 @@
along with libextractor; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
-
- This code was based on AVInfo 1.0 alpha 11
- (c) George Shuklin, gs]AT[shounen.ru, 2002-2004
- http://shounen.ru/soft/avinfo/
-
- and bitcollider 0.6.0
- (PD) 2004 The Bitzi Corporation
- http://bitzi.com/
*/
#include "platform.h"
#include "extractor.h"
-#include "pack.h"
-#include <math.h>
+#include <mpeg2dec/mpeg2.h>
static void addKeyword(struct EXTRACTOR_Keywords ** list,
char * keyword,
@@ -38,137 +29,83 @@ static void addKeyword(struct EXTRACTOR_Keywords ** list,
EXTRACTOR_KeywordList * next;
next = malloc(sizeof(EXTRACTOR_KeywordList));
next->next = *list;
- next->keyword = keyword;
+ next->keyword = strdup(keyword);
next->keywordType = type;
*list = next;
}
-/* We implement our own rounding function, because the availability of
- * C99's round(), nearbyint(), rint(), etc. seems to be spotty, whereas
- * floor() is available in math.h on all C compilers.
- */
-static double round_double(double num) {
- return floor(num + 0.5);
-}
-
-/* read big-endian number (most significant byte first) */
-static unsigned int fread_be(unsigned char * data) {
- int x;
- unsigned int result = 0;
-
- for (x=3;x>=0;x--)
- result |= data[4-x] << (x*8);
- return result;
-}
-
/* video/mpeg */
-struct EXTRACTOR_Keywords * libextractor_mpeg_extract(char * filename,
- unsigned char * xdata,
- size_t xsize,
- struct EXTRACTOR_Keywords * prev) {
- unsigned int version = 0;
- unsigned int bitrate = 0;
- unsigned int height = 0;
- unsigned int width = 0;
- unsigned int temp;
- unsigned int pos;
- char * format;
- int mixed = 0;
-
- if (xsize < 16)
+struct EXTRACTOR_Keywords *
+libextractor_mpeg_extract(const char * filename,
+ const unsigned char * data,
+ size_t size,
+ struct EXTRACTOR_Keywords * prev) {
+ mpeg2dec_t * handle;
+ uint8_t * start;
+ uint8_t * end;
+ const mpeg2_info_t * info;
+ mpeg2_state_t state;
+ char format[256];
+
+ if ( ! ( (data[0]==0x00) &&
+ (data[1]==0x00) &&
+ (data[2]==0x01) &&
+ ( (data[3]==0xB3) || (data[3]==0xBA) ) ) )
return prev;
- if ( ! ( (xdata[0]==0x00) &&
- (xdata[1]==0x00) &&
- (xdata[2]==0x01) &&
- ( (xdata[3]==0xB3) || (xdata[3]==0xBA) ) ) )
+ handle = mpeg2_init();
+ if (handle == NULL)
return prev;
-
- if (xdata[3] == 0xBA) {
- /* multiplexed audio/video */
- mixed = 1;
-
- if ((xdata[4] & 0xF0) == 0x20) /* binary 0010 xxxx */
- version = 1;
- else if((xdata[4] & 0xC0) == 0x40) /* binary 01xx xxxx */
- version = 2;
- else
- return prev; /* unsupported mpeg version */
-
- if (version == 1) {
- bitrate = round_double((double)((fread_be(&xdata[8]) & 0x7FFFFE) >> 1) * 0.4);
- pos = 12;
- } else {
- bitrate = round_double((double)((fread_be(&xdata[9]) & 0xFFFFFC) >> 2) * 0.4);
- temp = xdata[13] & 0x7;
- pos = 14 + temp;
- }
- if (pos + 4 >= xsize)
- return prev;
- temp = fread_be(&xdata[pos]);
- while ( (temp != 0x000001BA) && (temp != 0x000001E0) ) {
- if (temp == 0x00000000) {
- while ((temp & 0xFFFFFF00) != 0x00000100) {
- pos++;
- if (pos + 4 >= xsize)
- return prev;
- temp = fread_be(&xdata[pos]);
- }
- } else {
- if (pos + 4 >= xsize)
- return prev;
- temp = fread_be(&xdata[pos]) & 0xFFFF;
- pos += temp + 2;
- if (pos + 4 >= xsize)
- return prev;
- temp = fread_be(&xdata[pos]);
- }
- }
- pos += 4;
-
- if (pos + 4 >= xsize)
- return prev;
- /* Now read byte by byte until we find the 0x000001B3 instead of actually
- * parsing (due to too many variations). Theoretically this could mean
- * we find 0x000001B3 as data inside another packet, but that's extremely
- * unlikely, especially since the sequence header should not be far */
- temp = fread_be(&xdata[pos]);
- pos += 4;
- while (temp != 0x000001B3) {
- temp <<= 8;
- if (pos == xsize)
- return prev;
- temp |= xdata[pos++];
- }
- } else
- pos = 4; /* video only */
-
- if (pos + 16 >= xsize)
+ start = (uint8_t *) data;
+ end = (uint8_t *) &data[size];
+ mpeg2_buffer(handle, start, end);
+ state = mpeg2_parse(handle);
+ if (state != STATE_SEQUENCE) {
+ mpeg2_close(handle);
return prev;
- width = (xdata[pos] << 4) + (xdata[pos+1] & 0xF);
- height = ((xdata[pos+1] & 0xF0) << 4) + xdata[pos+2];
-
- addKeyword(&prev,
- strdup("video/mpeg"),
- EXTRACTOR_MIMETYPE);
- format = malloc(256);
- snprintf(format,
- 256,
- "MPEG%d (%s)",
- version,
- mixed ? "audio/video" : "video only");
- addKeyword(&prev,
- format,
- EXTRACTOR_FORMAT);
- format = malloc(256);
- snprintf(format,
- 256,
- "%ux%u",
- width,
- height);
+ }
+ info = mpeg2_info(handle);
+ if (info == NULL) {
+ mpeg2_close(handle);
+ return prev;
+ }
addKeyword(&prev,
- format,
- EXTRACTOR_SIZE);
- return prev;
+ "video/mpeg",
+ EXTRACTOR_MIMETYPE);
+ if (info->sequence != NULL) {
+ snprintf(format, 256, "%ux%u",
+ info->sequence->width,
+ info->sequence->height);
+ addKeyword(&prev, format, EXTRACTOR_SIZE);
+ switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED) {
+ case SEQ_VIDEO_FORMAT_PAL:
+ addKeyword(&prev, "PAL", EXTRACTOR_FORMAT);
+ break;
+ case SEQ_VIDEO_FORMAT_NTSC:
+ addKeyword(&prev, "NTSC", EXTRACTOR_FORMAT);
+ break;
+ case SEQ_VIDEO_FORMAT_SECAM:
+ addKeyword(&prev, "SECAM", EXTRACTOR_FORMAT);
+ break;
+ case SEQ_VIDEO_FORMAT_MAC:
+ addKeyword(&prev, "MAC", EXTRACTOR_FORMAT);
+ break;
+ default:
+ break;
+ }
+ if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0)
+ addKeyword(&prev, "MPEG2", EXTRACTOR_RESOURCE_TYPE);
+ else
+ addKeyword(&prev, "MPEG1", EXTRACTOR_RESOURCE_TYPE);
+ }
+ if (info->gop != NULL) {
+ snprintf(format, 256, "%u:%u:%u (%u frames)",
+ info->gop->hours,
+ info->gop->minutes,
+ info->gop->seconds,
+ info->gop->pictures);
+ addKeyword(&prev, format, EXTRACTOR_DURATION);
+ }
+ mpeg2_close(handle);
+ return prev;
}
-