libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

commit e3853cddfbcc012cf4433eef9f2d3901c4bc7188
parent 96fb8d67c9f0dc70101a34c862532528c9ec0076
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 17 May 2006 08:25:00 +0000

fixing mantis 826

Diffstat:
MChangeLog | 4++++
MREADME.debian | 1+
Mconfigure.ac | 12+++++++++++-
Msrc/plugins/Makefile.am | 2+-
Msrc/plugins/mpegextractor.c | 205++++++++++++++++++++++++++++---------------------------------------------------
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; } -