libextractor

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

commit ebf0f06f2ba192c0140681eb209d5e4b02a57f6f
parent 39a6d1b56a8c754f352fbdc755366b17d09d456f
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun,  5 Aug 2012 23:16:15 +0000

starting with mpeg support, GOP still not working

Diffstat:
Msrc/plugins/Makefile.am | 25+++++++++++++++++++++++--
Msrc/plugins/mpeg_extractor.c | 171+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Asrc/plugins/test_mpeg.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/testdata/mpeg_melt.mpg | 0
4 files changed, 205 insertions(+), 79 deletions(-)

diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am @@ -42,12 +42,19 @@ PLUGIN_FLAC=libextractor_flac.la TEST_FLAC=test_flac endif +if HAVE_MPEG2 +PLUGIN_MPEG=libextractor_mpeg.la +TEST_MPEG=test_mpeg +endif + + plugin_LTLIBRARIES = \ $(PLUGIN_OGG) \ $(PLUGIN_MIME) \ $(PLUGIN_GIF) \ $(PLUGIN_RPM) \ - $(PLUGIN_FLAC) + $(PLUGIN_FLAC) \ + $(PLUGIN_MPEG) if HAVE_ZZUF fuzz_tests=fuzz_default.sh @@ -58,7 +65,8 @@ check_PROGRAMS = \ $(TEST_MIME) \ $(TEST_GIF) \ $(TEST_RPM) \ - $(TEST_FLAC) + $(TEST_FLAC) \ + $(TEST_MPEG) TESTS = \ $(fuzz_tests) \ @@ -140,3 +148,16 @@ test_flac_LDADD = \ $(top_builddir)/src/plugins/libtest.la +libextractor_mpeg_la_SOURCES = \ + mpeg_extractor.c +libextractor_mpeg_la_LDFLAGS = \ + $(PLUGINFLAGS) +libextractor_mpeg_la_LIBADD = \ + -lmpeg2 + +test_mpeg_SOURCES = \ + test_mpeg.c +test_mpeg_LDADD = \ + $(top_builddir)/src/plugins/libtest.la + + diff --git a/src/plugins/mpeg_extractor.c b/src/plugins/mpeg_extractor.c @@ -1,11 +1,11 @@ /* This file is part of libextractor. - (C) 2004, 2005, 2006, 2009 Vidyut Samanta and Christian Grothoff + (C) 2004, 2005, 2006, 2009, 2012 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 - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. libextractor is distributed in the hope that it will be useful, but @@ -19,98 +19,115 @@ Boston, MA 02111-1307, USA. */ +/** + * @file plugins/mpeg_extractor.c + * @brief plugin to support MPEG files + * @author Christian Grothoff + */ #include "platform.h" #include "extractor.h" #include <mpeg2dec/mpeg2.h> -#define ADD(s,t) do { if (0 != (ret = proc (proc_cls, "mpeg", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1))) goto EXIT; } while (0) + +/** + * Give meta data to extractor. + * + * @param t type of the meta data + * @param s meta data value in utf8 format + */ +#define ADD(s,t) do { if (0 != ec->proc (ec->cls, "mpeg", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) goto EXIT; } while (0) -/* video/mpeg */ -int -EXTRACTOR_mpeg_extract (const unsigned char *data, - size_t size, - EXTRACTOR_MetaDataProcessor proc, - void *proc_cls, - const char *options) +/** + * Main entry method for the 'video/mpeg' extraction plugin. + * + * @param ec extraction context provided to the plugin + */ +void +EXTRACTOR_mpeg_extract_method (struct EXTRACTOR_ExtractContext *ec) { mpeg2dec_t *handle; - uint8_t *start; - uint8_t *end; const mpeg2_info_t *info; + void *buf; + ssize_t avail; mpeg2_state_t state; - int ret; char format[256]; + int finished; - if ((size < 4) || - (!((data[0] == 0x00) && - (data[1] == 0x00) && - (data[2] == 0x01) && ((data[3] == 0xB3) || (data[3] == 0xBA))))) - return 0; - - handle = mpeg2_init (); - if (handle == NULL) - return 0; - start = (uint8_t *) data; - end = (uint8_t *) & data[size]; - mpeg2_buffer (handle, start, end); - state = mpeg2_parse (handle); - if (state != STATE_SEQUENCE) + if (NULL == (handle = mpeg2_init ())) + return; + if (NULL == (info = mpeg2_info (handle))) { mpeg2_close (handle); - return 0; + return; } - info = mpeg2_info (handle); - if (info == NULL) + finished = 3; + while (0 != finished) { - mpeg2_close (handle); - return 0; - } - ret = 0; - ADD ("video/mpeg", EXTRACTOR_METATYPE_MIMETYPE); - if (info->sequence != NULL) - { - snprintf (format, - sizeof(format), "%ux%u", - info->sequence->width, info->sequence->height); - ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS); - switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED) - { - case SEQ_VIDEO_FORMAT_PAL: - ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); - break; - case SEQ_VIDEO_FORMAT_NTSC: - ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); - break; - case SEQ_VIDEO_FORMAT_SECAM: - ADD ("SECAM", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); - break; - case SEQ_VIDEO_FORMAT_MAC: - ADD ("MAC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); - break; - default: - break; - } - if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0) - ADD ("MPEG2", EXTRACTOR_METATYPE_FORMAT_VERSION); - else - ADD ("MPEG1", EXTRACTOR_METATYPE_FORMAT_VERSION); - } - if (info->gop != NULL) - { - /* this usually does not work yet, since gop's are not - often at the beginning of the stream (and we - don't iterate over the stream hoping to find one). - Hence we usually don't get the size. Not sure how - to *efficiently* get the gop (without scanning - through the entire file) */ - snprintf (format, - sizeof(format), "%u:%u:%u (%u frames)", - info->gop->hours, - info->gop->minutes, info->gop->seconds, info->gop->pictures); - ADD (format, EXTRACTOR_METATYPE_DURATION); + state = mpeg2_parse (handle); + switch (state) + { + case STATE_BUFFER: + if (0 >= (avail = ec->read (ec->cls, + &buf, + 16 * 1024))) + goto EXIT; + mpeg2_buffer (handle, buf, buf + avail); + break; + case STATE_SEQUENCE: + ADD ("video/mpeg", EXTRACTOR_METATYPE_MIMETYPE); + snprintf (format, + sizeof(format), "%ux%u", + info->sequence->width, info->sequence->height); + ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS); + switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED) + { + case SEQ_VIDEO_FORMAT_PAL: + ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); + break; + case SEQ_VIDEO_FORMAT_NTSC: + ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); + break; + case SEQ_VIDEO_FORMAT_SECAM: + ADD ("SECAM", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); + break; + case SEQ_VIDEO_FORMAT_MAC: + ADD ("MAC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); + break; + default: + break; + } + if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0) + ADD ("MPEG2", EXTRACTOR_METATYPE_FORMAT_VERSION); + else + ADD ("MPEG1", EXTRACTOR_METATYPE_FORMAT_VERSION); + finished &= ~2; + break; + case STATE_GOP: + if ( (NULL != info->gop) && + (0 != info->gop->pictures) ) + { + snprintf (format, + sizeof(format), + "%u:%u:%u (%u frames)", + info->gop->hours, + info->gop->minutes, info->gop->seconds, info->gop->pictures); + ADD (format, EXTRACTOR_METATYPE_DURATION); + finished &= ~1; + } + break; + case STATE_SLICE: + break; + case STATE_END: + break; + case STATE_INVALID: + goto EXIT; + default: + break; + } } EXIT: mpeg2_close (handle); - return ret; } + +/* end of mpeg_extractor.c */ diff --git a/src/plugins/test_mpeg.c b/src/plugins/test_mpeg.c @@ -0,0 +1,88 @@ +/* + This file is part of libextractor. + (C) 2012 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 + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + libextractor 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 libextractor; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file plugins/test_mpeg.c + * @brief testcase for mpeg plugin + * @author Christian Grothoff + */ +#include "platform.h" +#include "test_lib.h" + + + +/** + * Main function for the MPEG testcase. + * + * @param argc number of arguments (ignored) + * @param argv arguments (ignored) + * @return 0 on success + */ +int +main (int argc, char *argv[]) +{ + struct SolutionData melt_sol[] = + { + { + EXTRACTOR_METATYPE_MIMETYPE, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "video/mpeg", + strlen ("video/mpeg") + 1, + 0 + }, + { + EXTRACTOR_METATYPE_IMAGE_DIMENSIONS, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "320x208", + strlen ("320x208") + 1, + 0 + }, + { + EXTRACTOR_METATYPE_FORMAT_VERSION, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "MPEG1", + strlen ("MPEG1") + 1, + 0 + }, +#if 0 + /* GOP is somehow not working for this example */ + { + EXTRACTOR_METATYPE_DURATION, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "0:0:0 (0 frames)", /* FIXME: this is obviously the wrong answer */ + strlen ("0:0:0 (0 frames)") + 1, + 0 + }, +#endif + { 0, 0, NULL, NULL, 0, -1 } + }; + struct ProblemSet ps[] = + { + { "testdata/mpeg_melt.mpg", + melt_sol }, + { NULL, NULL } + }; + return ET_main ("mpeg", ps); +} + +/* end of test_mpeg.c */ diff --git a/src/plugins/testdata/mpeg_melt.mpg b/src/plugins/testdata/mpeg_melt.mpg Binary files differ.