From 5307edba27e65305173177ebbeb5759c0c60217a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 19 Dec 2009 13:42:26 +0000 Subject: breaking build, porting plugins incomplete --- README.debian | 2 + TODO | 11 +- src/plugins/Makefile.am | 94 ++-- src/plugins/id3v23_extractor.c | 219 +++++++++ src/plugins/id3v23extractor.c | 218 --------- src/plugins/id3v24_extractor.c | 230 +++++++++ src/plugins/id3v24extractor.c | 229 --------- src/plugins/id3v2_extractor.c | 155 ++++++ src/plugins/id3v2extractor.c | 167 ------- src/plugins/thumbnailextractorqt.cc | 273 ----------- src/plugins/thumbnailffmpeg/Makefile.am | 41 -- src/plugins/thumbnailffmpeg/README | 105 ---- .../thumbnailffmpeg/thumbnailextractorffmpeg.c | 528 -------------------- src/plugins/thumbnailffmpeg_extractor.c | 536 +++++++++++++++++++++ 14 files changed, 1193 insertions(+), 1615 deletions(-) create mode 100644 src/plugins/id3v23_extractor.c delete mode 100644 src/plugins/id3v23extractor.c create mode 100644 src/plugins/id3v24_extractor.c delete mode 100644 src/plugins/id3v24extractor.c create mode 100644 src/plugins/id3v2_extractor.c delete mode 100644 src/plugins/id3v2extractor.c delete mode 100644 src/plugins/thumbnailextractorqt.cc delete mode 100644 src/plugins/thumbnailffmpeg/Makefile.am delete mode 100644 src/plugins/thumbnailffmpeg/README delete mode 100644 src/plugins/thumbnailffmpeg/thumbnailextractorffmpeg.c create mode 100644 src/plugins/thumbnailffmpeg_extractor.c diff --git a/README.debian b/README.debian index e66daf8..ade7d37 100644 --- a/README.debian +++ b/README.debian @@ -20,6 +20,8 @@ libmpeg2-4-dev libqt4-dev librpm-dev libexiv2-dev # if you compile with --enable-exiv2 +libavformat-dev +libswscale-dev For Subversion access and compilation: diff --git a/TODO b/TODO index 2b8761d..cc8c6eb 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,15 @@ * ffmpeg needs make 3.81: add configure check for it Core: -* error reporting facilities -* add support for different character sets (to 'all' extractors) +* check for symbolic links, do not load same plugin twice! + (happens right now for installations with multiple + available thumbnailers) +* support "hash" plugins as *optional* plugins + (need a way to indicate that they should not be used + "by default") +* use "-" in config not to append plugin, but to remove one! +* document +* port test cases 'Unclean' code: * ASF diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 9244d14..a790d4d 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -86,6 +86,9 @@ plugin_LTLIBRARIES = \ libextractor_flv.la \ libextractor_gif.la \ libextractor_html.la \ + libextractor_id3v2.la \ + libextractor_id3v23.la \ + libextractor_id3v24.la \ libextractor_it.la \ libextractor_jpeg.la \ libextractor_man.la \ @@ -108,6 +111,8 @@ plugin_LTLIBRARIES = \ libextractor_sid.la \ libextractor_tar.la \ $(thumbgtk) \ + $(thumbqt) \ + $(thumbffmpeg) \ libextractor_tiff.la \ libextractor_wav.la \ libextractor_xm.la \ @@ -181,6 +186,27 @@ libextractor_html_la_LDFLAGS = \ libextractor_html_la_LIBADD = \ $(top_builddir)/src/common/libextractor_common.la +libextractor_id3v2_la_SOURCES = \ + id3v2_extractor.c +libextractor_id3v2_la_LDFLAGS = \ + $(PLUGINFLAGS) +libextractor_id3v2_la_LIBADD = \ + $(top_builddir)/src/common/libextractor_common.la + +libextractor_id3v23_la_SOURCES = \ + id3v23_extractor.c +libextractor_id3v23_la_LDFLAGS = \ + $(PLUGINFLAGS) +libextractor_id3v23_la_LIBADD = \ + $(top_builddir)/src/common/libextractor_common.la + +libextractor_id3v24_la_SOURCES = \ + id3v24_extractor.c +libextractor_id3v24_la_LDFLAGS = \ + $(PLUGINFLAGS) +libextractor_id3v24_la_LIBADD = \ + $(top_builddir)/src/common/libextractor_common.la + libextractor_it_la_SOURCES = \ it_extractor.c libextractor_it_la_LDFLAGS = \ @@ -318,6 +344,13 @@ libextractor_tar_la_SOURCES = \ libextractor_tar_la_LDFLAGS = \ $(PLUGINFLAGS) +libextractor_thumbnailffmpeg_la_SOURCES = \ + thumbnailffmpeg_extractor.c +libextractor_thumbnailffmpeg_la_LIBADD = \ + -lavformat -lavcodec -lswscale -lavutil -lz -lbz2 +libextractor_thumbnailffmpeg_la_LDFLAGS = \ + $(PLUGINFLAGS) + libextractor_thumbnailgtk_la_CFLAGS = \ $(GLIB_CFLAGS) $(GTK_CFLAGS) libextractor_thumbnailgtk_la_LIBADD = \ @@ -327,6 +360,15 @@ libextractor_thumbnailgtk_la_LDFLAGS = \ libextractor_thumbnailgtk_la_SOURCES = \ thumbnailgtk_extractor.c +libextractor_thumbnailqt_la_SOURCES = \ + thumbnailqt_extractor.cc +libextractor_thumbnailqt_la_LDFLAGS = \ + $(PLUGINFLAGS) +libextractor_thumbnailqt_la_LIBADD = \ + $(qtflags) $(svgflags) +libextractor_thumbnailqt_la_CPPFLAGS = \ + $(QT_CFLAGS) $(QT_SVG_CFLAGS) + libextractor_tiff_la_SOURCES = \ tiff_extractor.c libextractor_tiff_la_LDFLAGS = \ @@ -354,56 +396,6 @@ libextractor_zip_la_LDFLAGS = \ EXTRA_DIST = template_extractor.c - -# stuff below still needs to be ported to 0.6.x - -# SUBDIRS = . $(thumbffmpeg) hash - - -OLD_LIBS = \ - libextractor_id3v2.la \ - libextractor_id3v24.la \ - libextractor_id3v23.la \ - $(extrampeg) \ - $(thumbqt) - - -libextractor_id3v2_la_SOURCES = \ - id3v2extractor.c -libextractor_id3v2_la_LDFLAGS = \ - $(PLUGINFLAGS) -libextractor_id3v2_la_LIBADD = \ - $(top_builddir)/src/common/libextractor_common.la - -libextractor_id3v23_la_SOURCES = \ - id3v23extractor.c -libextractor_id3v23_la_LDFLAGS = \ - $(PLUGINFLAGS) -libextractor_id3v23_la_LIBADD = \ - $(top_builddir)/src/common/libextractor_common.la - -libextractor_id3v24_la_SOURCES = \ - id3v24extractor.c -libextractor_id3v24_la_LDFLAGS = \ - $(PLUGINFLAGS) -libextractor_id3v24_la_LIBADD = \ - $(top_builddir)/src/common/libextractor_common.la - - -libextractor_thumbnailqt_la_SOURCES = \ - thumbnailextractorqt.cc -libextractor_thumbnailqt_la_LDFLAGS = \ - $(PLUGINFLAGS) -libextractor_thumbnailqt_la_LIBADD = \ - $(qtflags) $(svgflags) \ - $(top_builddir)/src/main/libextractor.la -libextractor_thumbnailqt_la_CPPFLAGS = \ - -I$(top_scrdir)/include \ - $(QT_CFLAGS) $(QT_SVG_CFLAGS) - - -# FIXME: is this still working ok? Doubtful! - install-exec-hook: mkdir -p $(DESTDIR)$(plugindir) &> /dev/null || true rm -f $(DESTDIR)$(plugindir)/libextractor_thumbnail$(LIBEXT) @@ -422,5 +414,3 @@ install-exec-hook: fi \ fi \ fi - - diff --git a/src/plugins/id3v23_extractor.c b/src/plugins/id3v23_extractor.c new file mode 100644 index 0000000..11b04d9 --- /dev/null +++ b/src/plugins/id3v23_extractor.c @@ -0,0 +1,219 @@ +/* + This file is part of libextractor. + (C) 2002, 2003, 2004, 2006, 2007 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 + 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. + + */ +#define DEBUG_EXTRACT_ID3v23 0 + +#include "platform.h" +#include "extractor.h" +#include +#include +#include +#include +#include +#include +#include +#ifndef MINGW +#include +#endif + +#include "convert.h" + +static struct EXTRACTOR_Keywords * +addKeyword (EXTRACTOR_KeywordList * oldhead, + char *phrase, EXTRACTOR_KeywordType type) +{ + EXTRACTOR_KeywordList *keyword; + + keyword = malloc (sizeof (EXTRACTOR_KeywordList)); + keyword->next = oldhead; + keyword->keyword = phrase; + keyword->keywordType = type; + return keyword; +} + +typedef struct +{ + const char *text; + enum EXTRACTOR_MetaType type; +} Matches; + +static Matches tmap[] = { + {"COMM", EXTRACTOR_METATYPE_COMMENT}, + {"IPLS", EXTRACTOR_METATYPE_CONTRIBUTOR}, + {"LINK", EXTRACTOR_METATYPE_LINK}, + {"MCDI", EXTRACTOR_METATYPE_MUSIC_CD_IDENTIFIER}, + {"PCNT", EXTRACTOR_METATYPE_PLAY_COUNTER}, + {"POPM", EXTRACTOR_METATYPE_POPULARITY_METER}, + {"TCOP", EXTRACTOR_METATYPE_COPYRIGHT}, + {"TDAT", EXTRACTOR_METATYPE_DATE}, + {"TCON", EXTRACTOR_METATYPE_CONTENT_TYPE}, + {"TIT1", EXTRACTOR_METATYPE_GENRE}, + {"TENC", EXTRACTOR_METATYPE_ENCODED_BY}, + {"TEXT", EXTRACTOR_METATYPE_LYRICS}, + {"TOLY", EXTRACTOR_METATYPE_CONTRIBUTOR}, + {"TOPE", EXTRACTOR_METATYPE_CONTRIBUTOR}, + {"TOWN", EXTRACTOR_METATYPE_OWNER}, + {"TPE1", EXTRACTOR_METATYPE_ARTIST}, + {"TPE2", EXTRACTOR_METATYPE_ARTIST}, + {"TPE3", EXTRACTOR_METATYPE_CONDUCTOR}, + {"TPE4", EXTRACTOR_METATYPE_INTERPRET}, + {"TMED", EXTRACTOR_METATYPE_MEDIA_TYPE}, + {"TCOM", EXTRACTOR_METATYPE_CREATOR}, + {"TIME", EXTRACTOR_METATYPE_TIME}, + {"TOFN", EXTRACTOR_METATYPE_FILENAME}, + {"TOPE", EXTRACTOR_METATYPE_ARTIST}, + {"TPUB", EXTRACTOR_METATYPE_PUBLISHER}, + {"TRCK", EXTRACTOR_METATYPE_TRACK_NUMBER}, + {"TRSC", EXTRACTOR_METATYPE_ISRC}, + {"TRSN", EXTRACTOR_METATYPE_SOURCE}, + {"TRSO", EXTRACTOR_METATYPE_CREATED_FOR}, + {"TSRC", EXTRACTOR_METATYPE_RESOURCE_IDENTIFIER}, + {"TOAL", EXTRACTOR_METATYPE_ALBUM}, + {"TALB", EXTRACTOR_METATYPE_ALBUM}, + {"TLAN", EXTRACTOR_METATYPE_LANGUAGE}, + {"TYER", EXTRACTOR_METATYPE_YEAR}, + {"TLEN", EXTRACTOR_METATYPE_DURATION}, + {"TIT2", EXTRACTOR_METATYPE_TITLE}, + {"TIT3", EXTRACTOR_METATYPE_DESCRIPTION}, + {"WCOM", EXTRACTOR_METATYPE_RELEASE}, + {"WCOP", EXTRACTOR_METATYPE_DISCLAIMER}, + {"", EXTRACTOR_METATYPE_KEYWORDS}, + {NULL, 0} +}; + + +/* mimetype = audio/mpeg */ +int +EXTRACTOR_id3v23_extract (const unsigned char *data, + size_t size, + EXTRACTOR_MetaDataProcessor proc, + void *proc_cls, + const char *options) +{ + int unsync; + int extendedHdr; + int experimental; + uint32_t tsize; + uint32_t pos; + uint32_t ehdrSize; + uint32_t padding; + uint32_t csize; + int i; + uint16_t flags; + + if ((size < 16) || + (data[0] != 0x49) || + (data[1] != 0x44) || + (data[2] != 0x33) || (data[3] != 0x03) || (data[4] != 0x00)) + return prev; + unsync = (data[5] & 0x80) > 0; + extendedHdr = (data[5] & 0x40) > 0; + experimental = (data[5] & 0x20) > 0; + tsize = (((data[6] & 0x7F) << 21) | + ((data[7] & 0x7F) << 14) | + ((data[8] & 0x7F) << 7) | ((data[9] & 0x7F) << 0)); + if ((tsize + 10 > size) || (experimental)) + return prev; + pos = 10; + padding = 0; + if (extendedHdr) + { + ehdrSize = (((data[10]) << 24) | + ((data[11]) << 16) | ((data[12]) << 8) | ((data[12]) << 0)); + + padding = (((data[15]) << 24) | + ((data[16]) << 16) | ((data[17]) << 8) | ((data[18]) << 0)); + pos += 4 + ehdrSize; + if (padding < tsize) + tsize -= padding; + else + return prev; + } + + + while (pos < tsize) + { + if (pos + 10 > tsize) + return prev; + csize = + (data[pos + 4] << 24) + (data[pos + 5] << 16) + (data[pos + 6] << 8) + + data[pos + 7]; + if ((pos + 10 + csize > tsize) || (csize > tsize) || (csize == 0)) + break; + flags = (data[pos + 8] << 8) + data[pos + 9]; + if (((flags & 0x80) > 0) /* compressed, not yet supported */ || + ((flags & 0x40) > 0) /* encrypted, not supported */ ) + { + pos += 10 + csize; + continue; + } + i = 0; + while (tmap[i].text != NULL) + { + if (0 == strncmp (tmap[i].text, (const char *) &data[pos], 4)) + { + char *word; + if ((flags & 0x20) > 0) + { + /* "group" identifier, skip a byte */ + pos++; + csize--; + } + csize--; + /* this byte describes the encoding + try to convert strings to UTF-8 + if it fails, then forget it */ + switch (data[pos + 10]) + { + case 0x00: + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], + csize, "ISO-8859-1"); + break; + case 0x01: + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], + csize, "UCS-2"); + break; + default: + /* bad encoding byte, + try to convert from iso-8859-1 */ + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], + csize, "ISO-8859-1"); + break; + } + pos++; + if ((word != NULL) && (strlen (word) > 0)) + { + prev = addKeyword (prev, word, tmap[i].type); + } + else + { + if (word != NULL) + free (word); + } + break; + } + i++; + } + pos += 10 + csize; + } + return prev; +} + +/* end of id3v23_extractor.c */ diff --git a/src/plugins/id3v23extractor.c b/src/plugins/id3v23extractor.c deleted file mode 100644 index 7029e73..0000000 --- a/src/plugins/id3v23extractor.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - This file is part of libextractor. - (C) 2002, 2003, 2004, 2006, 2007 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 - 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. - - */ -#define DEBUG_EXTRACT_ID3v23 0 - -#include "platform.h" -#include "extractor.h" -#include -#include -#include -#include -#include -#include -#include -#ifndef MINGW -#include -#endif - -#include "convert.h" - -static struct EXTRACTOR_Keywords * -addKeyword (EXTRACTOR_KeywordList * oldhead, - char *phrase, EXTRACTOR_KeywordType type) -{ - EXTRACTOR_KeywordList *keyword; - - keyword = malloc (sizeof (EXTRACTOR_KeywordList)); - keyword->next = oldhead; - keyword->keyword = phrase; - keyword->keywordType = type; - return keyword; -} - -typedef struct -{ - const char *text; - EXTRACTOR_KeywordType type; -} Matches; - -static Matches tmap[] = { - {"COMM", EXTRACTOR_COMMENT}, - {"IPLS", EXTRACTOR_CONTRIBUTOR}, - {"LINK", EXTRACTOR_LINK}, - {"MCDI", EXTRACTOR_MUSIC_CD_IDENTIFIER}, - {"PCNT", EXTRACTOR_PLAY_COUNTER}, - {"POPM", EXTRACTOR_POPULARITY_METER}, - {"TCOP", EXTRACTOR_COPYRIGHT}, - {"TDAT", EXTRACTOR_DATE}, - {"TCON", EXTRACTOR_CONTENT_TYPE}, - {"TIT1", EXTRACTOR_GENRE}, - {"TENC", EXTRACTOR_ENCODED_BY}, - {"TEXT", EXTRACTOR_LYRICS}, - {"TOLY", EXTRACTOR_CONTRIBUTOR}, - {"TOPE", EXTRACTOR_CONTRIBUTOR}, - {"TOWN", EXTRACTOR_OWNER}, - {"TPE1", EXTRACTOR_ARTIST}, - {"TPE2", EXTRACTOR_ARTIST}, - {"TPE3", EXTRACTOR_CONDUCTOR}, - {"TPE4", EXTRACTOR_INTERPRET}, - {"TMED", EXTRACTOR_MEDIA_TYPE}, - {"TCOM", EXTRACTOR_CREATOR}, - {"TIME", EXTRACTOR_TIME}, - {"TOFN", EXTRACTOR_FILENAME}, - {"TOPE", EXTRACTOR_ARTIST}, - {"TPUB", EXTRACTOR_PUBLISHER}, - {"TRCK", EXTRACTOR_TRACK_NUMBER}, - {"TRSC", EXTRACTOR_ISRC}, - {"TRSN", EXTRACTOR_SOURCE}, - {"TRSO", EXTRACTOR_CREATED_FOR}, - {"TSRC", EXTRACTOR_RESOURCE_IDENTIFIER}, - {"TOAL", EXTRACTOR_ALBUM}, - {"TALB", EXTRACTOR_ALBUM}, - {"TLAN", EXTRACTOR_LANGUAGE}, - {"TYER", EXTRACTOR_YEAR}, - {"TLEN", EXTRACTOR_DURATION}, - {"TIT2", EXTRACTOR_TITLE}, - {"TIT3", EXTRACTOR_DESCRIPTION}, - {"WCOM", EXTRACTOR_RELEASE}, - {"WCOP", EXTRACTOR_DISCLAIMER}, - {"", EXTRACTOR_KEYWORDS}, - {NULL, 0}, -}; - - -/* mimetype = audio/mpeg */ -struct EXTRACTOR_Keywords * -libextractor_id3v23_extract (const char *filename, - const unsigned char *data, - const size_t size, - struct EXTRACTOR_Keywords *prev) -{ - int unsync; - int extendedHdr; - int experimental; - uint32_t tsize; - uint32_t pos; - uint32_t ehdrSize; - uint32_t padding; - uint32_t csize; - int i; - uint16_t flags; - - if ((size < 16) || - (data[0] != 0x49) || - (data[1] != 0x44) || - (data[2] != 0x33) || (data[3] != 0x03) || (data[4] != 0x00)) - return prev; - unsync = (data[5] & 0x80) > 0; - extendedHdr = (data[5] & 0x40) > 0; - experimental = (data[5] & 0x20) > 0; - tsize = (((data[6] & 0x7F) << 21) | - ((data[7] & 0x7F) << 14) | - ((data[8] & 0x7F) << 7) | ((data[9] & 0x7F) << 0)); - if ((tsize + 10 > size) || (experimental)) - return prev; - pos = 10; - padding = 0; - if (extendedHdr) - { - ehdrSize = (((data[10]) << 24) | - ((data[11]) << 16) | ((data[12]) << 8) | ((data[12]) << 0)); - - padding = (((data[15]) << 24) | - ((data[16]) << 16) | ((data[17]) << 8) | ((data[18]) << 0)); - pos += 4 + ehdrSize; - if (padding < tsize) - tsize -= padding; - else - return prev; - } - - - while (pos < tsize) - { - if (pos + 10 > tsize) - return prev; - csize = - (data[pos + 4] << 24) + (data[pos + 5] << 16) + (data[pos + 6] << 8) + - data[pos + 7]; - if ((pos + 10 + csize > tsize) || (csize > tsize) || (csize == 0)) - break; - flags = (data[pos + 8] << 8) + data[pos + 9]; - if (((flags & 0x80) > 0) /* compressed, not yet supported */ || - ((flags & 0x40) > 0) /* encrypted, not supported */ ) - { - pos += 10 + csize; - continue; - } - i = 0; - while (tmap[i].text != NULL) - { - if (0 == strncmp (tmap[i].text, (const char *) &data[pos], 4)) - { - char *word; - if ((flags & 0x20) > 0) - { - /* "group" identifier, skip a byte */ - pos++; - csize--; - } - csize--; - /* this byte describes the encoding - try to convert strings to UTF-8 - if it fails, then forget it */ - switch (data[pos + 10]) - { - case 0x00: - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], - csize, "ISO-8859-1"); - break; - case 0x01: - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], - csize, "UCS-2"); - break; - default: - /* bad encoding byte, - try to convert from iso-8859-1 */ - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], - csize, "ISO-8859-1"); - break; - } - pos++; - if ((word != NULL) && (strlen (word) > 0)) - { - prev = addKeyword (prev, word, tmap[i].type); - } - else - { - if (word != NULL) - free (word); - } - break; - } - i++; - } - pos += 10 + csize; - } - return prev; -} - -/* end of id3v23extractor.c */ diff --git a/src/plugins/id3v24_extractor.c b/src/plugins/id3v24_extractor.c new file mode 100644 index 0000000..ec11e4a --- /dev/null +++ b/src/plugins/id3v24_extractor.c @@ -0,0 +1,230 @@ +/* + This file is part of libextractor. + (C) 2002, 2003, 2004, 2006, 2009 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 + 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. + + */ + +#define DEBUG_EXTRACT_ID3v24 0 + +#include "platform.h" +#include "extractor.h" +#include +#include +#include +#include +#include +#include +#include +#ifndef MINGW +#include +#endif +#include "convert.h" + + +static struct EXTRACTOR_Keywords * +addKeyword (EXTRACTOR_KeywordList * oldhead, + char *phrase, EXTRACTOR_KeywordType type) +{ + EXTRACTOR_KeywordList *keyword; + + keyword = malloc (sizeof (EXTRACTOR_KeywordList)); + keyword->next = oldhead; + keyword->keyword = phrase; + keyword->keywordType = type; + return keyword; +} + +typedef struct +{ + char *text; + enum EXTRACTOR_MetaType type; +} Matches; + +static Matches tmap[] = { + {"COMM", EXTRACTOR_METATYPE_COMMENT}, + {"IPLS", EXTRACTOR_METATYPE_CONTRIBUTOR}, + {"TIPL", EXTRACTOR_METATYPE_CONTRIBUTOR}, + {"TMOO", EXTRACTOR_METATYPE_MOOD}, + {"TMCL", EXTRACTOR_METATYPE_MUSICIAN_CREDITS_LIST}, + {"LINK", EXTRACTOR_METATYPE_LINK}, + {"MCDI", EXTRACTOR_METATYPE_MUSIC_CD_IDENTIFIER}, + {"PCNT", EXTRACTOR_METATYPE_PLAY_COUNTER}, + {"POPM", EXTRACTOR_METATYPE_POPULARITY_METER}, + {"TCOP", EXTRACTOR_METATYPE_COPYRIGHT}, + {"TDRC", EXTRACTOR_METATYPE_DATE}, + {"TCON", EXTRACTOR_METATYPE_GENRE}, + {"TIT1", EXTRACTOR_METATYPE_GENRE}, + {"TENC", EXTRACTOR_METATYPE_ENCODED_BY}, + {"TEXT", EXTRACTOR_METATYPE_LYRICS}, + {"TOLY", EXTRACTOR_METATYPE_CONTRIBUTOR}, + {"TOPE", EXTRACTOR_METATYPE_CONTRIBUTOR}, + {"TOWN", EXTRACTOR_METATYPE_OWNER}, + {"TPE1", EXTRACTOR_METATYPE_ARTIST}, + {"TPE2", EXTRACTOR_METATYPE_ARTIST}, + {"TPE3", EXTRACTOR_METATYPE_CONDUCTOR}, + {"TPE4", EXTRACTOR_METATYPE_INTERPRET}, + {"TIME", EXTRACTOR_METATYPE_TIME}, + {"TMED", EXTRACTOR_METATYPE_MEDIA_TYPE}, + {"TCOM", EXTRACTOR_METATYPE_CREATOR}, + {"TOFN", EXTRACTOR_METATYPE_FILENAME}, + {"TOPE", EXTRACTOR_METATYPE_ARTIST}, + {"TPUB", EXTRACTOR_METATYPE_PUBLISHER}, + {"TRCK", EXTRACTOR_METATYPE_TRACK_NUMBER}, + {"TRSC", EXTRACTOR_METATYPE_ISRC}, + {"TRSN", EXTRACTOR_METATYPE_SOURCE}, + {"TRSO", EXTRACTOR_METATYPE_CREATED_FOR}, + {"TSRC", EXTRACTOR_METATYPE_RESOURCE_IDENTIFIER}, + {"TYER", EXTRACTOR_METATYPE_YEAR}, + {"TOAL", EXTRACTOR_METATYPE_ALBUM}, + {"TALB", EXTRACTOR_METATYPE_ALBUM}, + {"TLAN", EXTRACTOR_METATYPE_LANGUAGE}, + {"TIT2", EXTRACTOR_METATYPE_TITLE}, + {"TIT3", EXTRACTOR_METATYPE_DESCRIPTION}, + {"WCOM", EXTRACTOR_METATYPE_RELEASE}, + {"WCOP", EXTRACTOR_METATYPE_DISCLAIMER}, + {"", EXTRACTOR_METATYPE_KEYWORDS}, + {NULL, 0} +}; + + +/* mimetype = audio/mpeg */ +int +EXTRACTOR_id3v24_extract (const unsigned char *data, + size_t size, + EXTRACTOR_MetaDataProcessor proc, + void *proc_cls, + const char *options) +{ + int unsync; + int extendedHdr; + int experimental; + int footer; + unsigned int tsize; + unsigned int pos; + unsigned int ehdrSize; + unsigned int padding; + + if ((size < 16) || + (data[0] != 0x49) || + (data[1] != 0x44) || + (data[2] != 0x33) || (data[3] != 0x04) || (data[4] != 0x00)) + return prev; + unsync = (data[5] & 0x80) > 0; + extendedHdr = (data[5] & 0x40) > 0; + experimental = (data[5] & 0x20) > 0; + footer = (data[5] & 0x10) > 0; + tsize = (((data[6] & 0x7F) << 21) | + ((data[7] & 0x7F) << 14) | + ((data[8] & 0x7F) << 7) | ((data[9] & 0x7F) << 0)); + if ((tsize + 10 > size) || (experimental)) + return prev; + pos = 10; + padding = 0; + if (extendedHdr) + { + ehdrSize = (((data[10] & 0x7F) << 21) | + ((data[11] & 0x7F) << 14) | + ((data[12] & 0x7F) << 7) | ((data[13] & 0x7F) << 0)); + pos += ehdrSize; + } + + + while (pos < tsize) + { + size_t csize; + int i; + unsigned short flags; + + if (pos + 10 > tsize) + return prev; + + csize = (((data[pos + 4] & 0x7F) << 21) | + ((data[pos + 5] & 0x7F) << 14) | + ((data[pos + 6] & 0x7F) << 7) | ((data[pos + 7] & 0x7F) << 0)); + + if ((pos + 10 + csize > tsize) || (csize > tsize) || (csize == 0)) + break; + flags = (data[pos + 8] << 8) + data[pos + 9]; + if (((flags & 0x80) > 0) /* compressed, not yet supported */ || + ((flags & 0x40) > 0) /* encrypted, not supported */ ) + { + pos += 10 + csize; + continue; + } + i = 0; + while (tmap[i].text != NULL) + { + if (0 == strncmp (tmap[i].text, (const char *) &data[pos], 4)) + { + char *word; + if ((flags & 0x20) > 0) + { + /* "group" identifier, skip a byte */ + pos++; + csize--; + } + + /* this byte describes the encoding + try to convert strings to UTF-8 + if it fails, then forget it */ + csize--; + switch (data[pos + 10]) + { + case 0x00: + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], + csize, "ISO-8859-1"); + break; + case 0x01: + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], + csize, "UTF-16"); + break; + case 0x02: + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], + csize, "UTF-16BE"); + break; + case 0x03: + word = malloc (csize + 1); + memcpy (word, &data[pos + 11], csize); + word[csize] = '\0'; + break; + default: + /* bad encoding byte, + try to convert from iso-8859-1 */ + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], + csize, "ISO-8859-1"); + break; + } + pos++; + if ((word != NULL) && (strlen (word) > 0)) + { + prev = addKeyword (prev, word, tmap[i].type); + } + else + { + free (word); + } + break; + } + i++; + } + pos += 10 + csize; + } + return prev; +} + +/* end of id3v24_extractor.c */ diff --git a/src/plugins/id3v24extractor.c b/src/plugins/id3v24extractor.c deleted file mode 100644 index cb0231e..0000000 --- a/src/plugins/id3v24extractor.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - This file is part of libextractor. - (C) 2002, 2003, 2004, 2006, 2009 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 - 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. - - */ - -#define DEBUG_EXTRACT_ID3v24 0 - -#include "platform.h" -#include "extractor.h" -#include -#include -#include -#include -#include -#include -#include -#ifndef MINGW -#include -#endif -#include "convert.h" - - -static struct EXTRACTOR_Keywords * -addKeyword (EXTRACTOR_KeywordList * oldhead, - char *phrase, EXTRACTOR_KeywordType type) -{ - EXTRACTOR_KeywordList *keyword; - - keyword = malloc (sizeof (EXTRACTOR_KeywordList)); - keyword->next = oldhead; - keyword->keyword = phrase; - keyword->keywordType = type; - return keyword; -} - -typedef struct -{ - char *text; - EXTRACTOR_KeywordType type; -} Matches; - -static Matches tmap[] = { - {"COMM", EXTRACTOR_COMMENT}, - {"IPLS", EXTRACTOR_CONTRIBUTOR}, - {"TIPL", EXTRACTOR_CONTRIBUTOR}, - {"TMOO", EXTRACTOR_MOOD}, - {"TMCL", EXTRACTOR_MUSICIAN_CREDITS_LIST}, - {"LINK", EXTRACTOR_LINK}, - {"MCDI", EXTRACTOR_MUSIC_CD_IDENTIFIER}, - {"PCNT", EXTRACTOR_PLAY_COUNTER}, - {"POPM", EXTRACTOR_POPULARITY_METER}, - {"TCOP", EXTRACTOR_COPYRIGHT}, - {"TDRC", EXTRACTOR_DATE}, - {"TCON", EXTRACTOR_GENRE}, - {"TIT1", EXTRACTOR_GENRE}, - {"TENC", EXTRACTOR_ENCODED_BY}, - {"TEXT", EXTRACTOR_LYRICS}, - {"TOLY", EXTRACTOR_CONTRIBUTOR}, - {"TOPE", EXTRACTOR_CONTRIBUTOR}, - {"TOWN", EXTRACTOR_OWNER}, - {"TPE1", EXTRACTOR_ARTIST}, - {"TPE2", EXTRACTOR_ARTIST}, - {"TPE3", EXTRACTOR_CONDUCTOR}, - {"TPE4", EXTRACTOR_INTERPRET}, - {"TIME", EXTRACTOR_TIME}, - {"TMED", EXTRACTOR_MEDIA_TYPE}, - {"TCOM", EXTRACTOR_CREATOR}, - {"TOFN", EXTRACTOR_FILENAME}, - {"TOPE", EXTRACTOR_ARTIST}, - {"TPUB", EXTRACTOR_PUBLISHER}, - {"TRCK", EXTRACTOR_TRACK_NUMBER}, - {"TRSC", EXTRACTOR_ISRC}, - {"TRSN", EXTRACTOR_SOURCE}, - {"TRSO", EXTRACTOR_CREATED_FOR}, - {"TSRC", EXTRACTOR_RESOURCE_IDENTIFIER}, - {"TYER", EXTRACTOR_YEAR}, - {"TOAL", EXTRACTOR_ALBUM}, - {"TALB", EXTRACTOR_ALBUM}, - {"TLAN", EXTRACTOR_LANGUAGE}, - {"TIT2", EXTRACTOR_TITLE}, - {"TIT3", EXTRACTOR_DESCRIPTION}, - {"WCOM", EXTRACTOR_RELEASE}, - {"WCOP", EXTRACTOR_DISCLAIMER}, - {"", EXTRACTOR_KEYWORDS}, - {NULL, 0}, -}; - - -/* mimetype = audio/mpeg */ -struct EXTRACTOR_Keywords * -libextractor_id3v24_extract (const char *filename, - const unsigned char *data, - const size_t size, - struct EXTRACTOR_Keywords *prev) -{ - int unsync; - int extendedHdr; - int experimental; - int footer; - unsigned int tsize; - unsigned int pos; - unsigned int ehdrSize; - unsigned int padding; - - if ((size < 16) || - (data[0] != 0x49) || - (data[1] != 0x44) || - (data[2] != 0x33) || (data[3] != 0x04) || (data[4] != 0x00)) - return prev; - unsync = (data[5] & 0x80) > 0; - extendedHdr = (data[5] & 0x40) > 0; - experimental = (data[5] & 0x20) > 0; - footer = (data[5] & 0x10) > 0; - tsize = (((data[6] & 0x7F) << 21) | - ((data[7] & 0x7F) << 14) | - ((data[8] & 0x7F) << 7) | ((data[9] & 0x7F) << 0)); - if ((tsize + 10 > size) || (experimental)) - return prev; - pos = 10; - padding = 0; - if (extendedHdr) - { - ehdrSize = (((data[10] & 0x7F) << 21) | - ((data[11] & 0x7F) << 14) | - ((data[12] & 0x7F) << 7) | ((data[13] & 0x7F) << 0)); - pos += ehdrSize; - } - - - while (pos < tsize) - { - size_t csize; - int i; - unsigned short flags; - - if (pos + 10 > tsize) - return prev; - - csize = (((data[pos + 4] & 0x7F) << 21) | - ((data[pos + 5] & 0x7F) << 14) | - ((data[pos + 6] & 0x7F) << 7) | ((data[pos + 7] & 0x7F) << 0)); - - if ((pos + 10 + csize > tsize) || (csize > tsize) || (csize == 0)) - break; - flags = (data[pos + 8] << 8) + data[pos + 9]; - if (((flags & 0x80) > 0) /* compressed, not yet supported */ || - ((flags & 0x40) > 0) /* encrypted, not supported */ ) - { - pos += 10 + csize; - continue; - } - i = 0; - while (tmap[i].text != NULL) - { - if (0 == strncmp (tmap[i].text, (const char *) &data[pos], 4)) - { - char *word; - if ((flags & 0x20) > 0) - { - /* "group" identifier, skip a byte */ - pos++; - csize--; - } - - /* this byte describes the encoding - try to convert strings to UTF-8 - if it fails, then forget it */ - csize--; - switch (data[pos + 10]) - { - case 0x00: - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], - csize, "ISO-8859-1"); - break; - case 0x01: - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], - csize, "UTF-16"); - break; - case 0x02: - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], - csize, "UTF-16BE"); - break; - case 0x03: - word = malloc (csize + 1); - memcpy (word, &data[pos + 11], csize); - word[csize] = '\0'; - break; - default: - /* bad encoding byte, - try to convert from iso-8859-1 */ - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 11], - csize, "ISO-8859-1"); - break; - } - pos++; - if ((word != NULL) && (strlen (word) > 0)) - { - prev = addKeyword (prev, word, tmap[i].type); - } - else - { - free (word); - } - break; - } - i++; - } - pos += 10 + csize; - } - return prev; -} - -/* end of id3v24extractor.c */ diff --git a/src/plugins/id3v2_extractor.c b/src/plugins/id3v2_extractor.c new file mode 100644 index 0000000..fa5fea6 --- /dev/null +++ b/src/plugins/id3v2_extractor.c @@ -0,0 +1,155 @@ +/* + This file is part of libextractor. + (C) 2002, 2003, 2004, 2006, 2009 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 + 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. + + */ + +#include "platform.h" +#include "extractor.h" +#ifndef MINGW +#include +#endif +#include "convert.h" + +#define DEBUG_EXTRACT_ID3v2 0 + +typedef struct +{ + const char *text; + enum EXTRACTOR_MetaType type; +} Matches; + +static Matches tmap[] = { + {"TAL", EXTRACTOR_METATYPE_TITLE}, + {"TT1", EXTRACTOR_METATYPE_GROUP}, + {"TT2", EXTRACTOR_METATYPE_TITLE}, + {"TT3", EXTRACTOR_METATYPE_TITLE}, + {"TXT", EXTRACTOR_METATYPE_DESCRIPTION}, + {"TPB", EXTRACTOR_METATYPE_PUBLISHER}, + {"WAF", EXTRACTOR_METATYPE_LOCATION}, + {"WAR", EXTRACTOR_METATYPE_LOCATION}, + {"WAS", EXTRACTOR_METATYPE_LOCATION}, + {"WCP", EXTRACTOR_METATYPE_COPYRIGHT}, + {"WAF", EXTRACTOR_METATYPE_LOCATION}, + {"WCM", EXTRACTOR_METATYPE_DISCLAIMER}, + {"TSS", EXTRACTOR_METATYPE_FORMAT}, + {"TYE", EXTRACTOR_METATYPE_DATE}, + {"TLA", EXTRACTOR_METATYPE_LANGUAGE}, + {"TP1", EXTRACTOR_METATYPE_ARTIST}, + {"TP2", EXTRACTOR_METATYPE_ARTIST}, + {"TP3", EXTRACTOR_METATYPE_CONDUCTOR}, + {"TP4", EXTRACTOR_METATYPE_INTERPRET}, + {"IPL", EXTRACTOR_METATYPE_CONTRIBUTOR}, + {"TOF", EXTRACTOR_METATYPE_FILENAME}, + {"TEN", EXTRACTOR_METATYPE_PRODUCER}, + {"TCO", EXTRACTOR_METATYPE_SUBJECT}, + {"TCR", EXTRACTOR_METATYPE_COPYRIGHT}, + {"SLT", EXTRACTOR_METATYPE_LYRICS}, + {"TOA", EXTRACTOR_METATYPE_ARTIST}, + {"TRC", EXTRACTOR_METATYPE_ISRC}, + {"TRK", EXTRACTOR_METATYPE_TRACK_NUMBER}, + {"TCM", EXTRACTOR_METATYPE_CREATOR}, + {"TOT", EXTRACTOR_METATYPE_ALBUM}, + {"TOL", EXTRACTOR_METATYPE_AUTHOR}, + {"COM", EXTRACTOR_METATYPE_COMMENT}, + {"", EXTRACTOR_METATYPE_KEYWORDS}, + {NULL, 0}, +}; + + +/* mimetype = audio/mpeg */ +int +EXTRACTOR_id3v2_extract (const unsigned char *data, + size_t size, + EXTRACTOR_MetaDataProcessor proc, + void *proc_cls, + const char *options) +{ + int unsync; + unsigned int tsize; + unsigned int pos; + + if ((size < 16) || + (data[0] != 0x49) || + (data[1] != 0x44) || + (data[2] != 0x33) || (data[3] != 0x02) || (data[4] != 0x00)) + return 0; + unsync = (data[5] & 0x80) > 0; + tsize = (((data[6] & 0x7F) << 21) | + ((data[7] & 0x7F) << 14) | + ((data[8] & 0x7F) << 07) | ((data[9] & 0x7F) << 00)); + + if (tsize + 10 > size) + return 0; + pos = 10; + while (pos < tsize) + { + size_t csize; + int i; + + if (pos + 6 > tsize) + return 0; + csize = (data[pos + 3] << 16) + (data[pos + 4] << 8) + data[pos + 5]; + if ((pos + 6 + csize > tsize) || (csize > tsize) || (csize == 0)) + break; + i = 0; + while (tmap[i].text != NULL) + { + if (0 == strncmp (tmap[i].text, (const char *) &data[pos], 3)) + { + char *word; + /* this byte describes the encoding + try to convert strings to UTF-8 + if it fails, then forget it */ + switch (data[pos + 6]) + { + case 0x00: + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 7], + csize, "ISO-8859-1"); + break; + case 0x01: + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 7], + csize, "UCS-2"); + break; + default: + /* bad encoding byte, + try to convert from iso-8859-1 */ + word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 7], + csize, "ISO-8859-1"); + break; + } + pos++; + csize--; + if ((word != NULL) && (strlen (word) > 0)) + { + prev = addKeyword (prev, word, tmap[i].type); + } + else + { + free (word); + } + break; + } + i++; + } + pos += 6 + csize; + } + return 0; +} + +/* end of id3v2_extractor.c */ diff --git a/src/plugins/id3v2extractor.c b/src/plugins/id3v2extractor.c deleted file mode 100644 index 00e353c..0000000 --- a/src/plugins/id3v2extractor.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - This file is part of libextractor. - (C) 2002, 2003, 2004, 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 - by the Free Software Foundation; either version 2, 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. - - */ - -#include "platform.h" -#include "extractor.h" -#ifndef MINGW -#include -#endif -#include "convert.h" - -#define DEBUG_EXTRACT_ID3v2 0 - - -static struct EXTRACTOR_Keywords * -addKeyword (EXTRACTOR_KeywordList * oldhead, - char *phrase, EXTRACTOR_KeywordType type) -{ - EXTRACTOR_KeywordList *keyword; - - keyword = (EXTRACTOR_KeywordList *) malloc (sizeof (EXTRACTOR_KeywordList)); - keyword->next = oldhead; - keyword->keyword = phrase; - keyword->keywordType = type; - return keyword; -} - -typedef struct -{ - char *text; - EXTRACTOR_KeywordType type; -} Matches; - -static Matches tmap[] = { - {"TAL", EXTRACTOR_TITLE}, - {"TT1", EXTRACTOR_GROUP}, - {"TT2", EXTRACTOR_TITLE}, - {"TT3", EXTRACTOR_TITLE}, - {"TXT", EXTRACTOR_DESCRIPTION}, - {"TPB", EXTRACTOR_PUBLISHER}, - {"WAF", EXTRACTOR_LOCATION}, - {"WAR", EXTRACTOR_LOCATION}, - {"WAS", EXTRACTOR_LOCATION}, - {"WCP", EXTRACTOR_COPYRIGHT}, - {"WAF", EXTRACTOR_LOCATION}, - {"WCM", EXTRACTOR_DISCLAIMER}, - {"TSS", EXTRACTOR_FORMAT}, - {"TYE", EXTRACTOR_DATE}, - {"TLA", EXTRACTOR_LANGUAGE}, - {"TP1", EXTRACTOR_ARTIST}, - {"TP2", EXTRACTOR_ARTIST}, - {"TP3", EXTRACTOR_CONDUCTOR}, - {"TP4", EXTRACTOR_INTERPRET}, - {"IPL", EXTRACTOR_CONTRIBUTOR}, - {"TOF", EXTRACTOR_FILENAME}, - {"TEN", EXTRACTOR_PRODUCER}, - {"TCO", EXTRACTOR_SUBJECT}, - {"TCR", EXTRACTOR_COPYRIGHT}, - {"SLT", EXTRACTOR_LYRICS}, - {"TOA", EXTRACTOR_ARTIST}, - {"TRC", EXTRACTOR_ISRC}, - {"TRK", EXTRACTOR_TRACK_NUMBER}, - {"TCM", EXTRACTOR_CREATOR}, - {"TOT", EXTRACTOR_ALBUM}, - {"TOL", EXTRACTOR_AUTHOR}, - {"COM", EXTRACTOR_COMMENT}, - {"", EXTRACTOR_KEYWORDS}, - {NULL, 0}, -}; - - -/* mimetype = audio/mpeg */ -struct EXTRACTOR_Keywords * -libextractor_id3v2_extract (const char *filename, - const unsigned char *data, - size_t size, struct EXTRACTOR_Keywords *prev) -{ - int unsync; - unsigned int tsize; - unsigned int pos; - - if ((size < 16) || - (data[0] != 0x49) || - (data[1] != 0x44) || - (data[2] != 0x33) || (data[3] != 0x02) || (data[4] != 0x00)) - return prev; - unsync = (data[5] & 0x80) > 0; - tsize = (((data[6] & 0x7F) << 21) | - ((data[7] & 0x7F) << 14) | - ((data[8] & 0x7F) << 07) | ((data[9] & 0x7F) << 00)); - - if (tsize + 10 > size) - return prev; - pos = 10; - while (pos < tsize) - { - size_t csize; - int i; - - if (pos + 6 > tsize) - return prev; - csize = (data[pos + 3] << 16) + (data[pos + 4] << 8) + data[pos + 5]; - if ((pos + 6 + csize > tsize) || (csize > tsize) || (csize == 0)) - break; - i = 0; - while (tmap[i].text != NULL) - { - if (0 == strncmp (tmap[i].text, (const char *) &data[pos], 3)) - { - char *word; - /* this byte describes the encoding - try to convert strings to UTF-8 - if it fails, then forget it */ - switch (data[pos + 6]) - { - case 0x00: - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 7], - csize, "ISO-8859-1"); - break; - case 0x01: - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 7], - csize, "UCS-2"); - break; - default: - /* bad encoding byte, - try to convert from iso-8859-1 */ - word = EXTRACTOR_common_convert_to_utf8 ((const char *) &data[pos + 7], - csize, "ISO-8859-1"); - break; - } - pos++; - csize--; - if ((word != NULL) && (strlen (word) > 0)) - { - prev = addKeyword (prev, word, tmap[i].type); - } - else - { - free (word); - } - break; - } - i++; - } - pos += 6 + csize; - } - return prev; -} - -/* end of id3v2extractor.c */ diff --git a/src/plugins/thumbnailextractorqt.cc b/src/plugins/thumbnailextractorqt.cc deleted file mode 100644 index 9ab3079..0000000 --- a/src/plugins/thumbnailextractorqt.cc +++ /dev/null @@ -1,273 +0,0 @@ -/* - This file is part of libextractor. - (C) 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 - by the Free Software Foundation; either version 2, 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 thumbnailextractorqt.cc - * @author Nils Durner - * @brief this extractor produces a binary (!) encoded - * thumbnail of images (using Qt). - */ - -#include "platform.h" -#include "extractor.h" -#include -#include -#include -#include -#include - -#ifdef HAVE_QT_SVG - #include - #include -#endif - -#define THUMBSIZE 128 - -extern "C" -{ - -static EXTRACTOR_KeywordList * addKeyword(EXTRACTOR_KeywordType type, - char * keyword, - EXTRACTOR_KeywordList * next) { - EXTRACTOR_KeywordList * result; - - if (keyword == NULL) - return next; - result = (EXTRACTOR_KeywordList *) malloc(sizeof(EXTRACTOR_KeywordList)); - result->next = next; - result->keyword = keyword; - result->keywordType = type; - return result; -} - - -/* which mime-types maybe subjected to - the thumbnail extractor (ImageMagick - crashes and/or prints errors for bad - formats, so we need to be rather - conservative here) */ -static const char * whitelist[] = { - "image/x-bmp", - "image/gif", - "image/jpeg", - "image/png", - "image/x-png", - "image/x-portable-bitmap", - "image/x-portable-graymap", - "image/x-portable-pixmap", - "image/x-xbitmap", - "image/x-xpixmap" - "image/x-xpm", -#ifdef HAVE_QT_SVG - "image/svg+xml", -#endif - NULL -}; - -static struct EXTRACTOR_Keywords * -extract(const unsigned char * data, - size_t size, - struct EXTRACTOR_Keywords * prev, - const char * options) { - QImage *img; - QByteArray bytes; - QBuffer buffer; - unsigned long width; - unsigned long height; - char * binary; - const char * mime; - int j; - char * format; - QImage::Format colors; - - /* if the mime-type of the file is not whitelisted - do not run the thumbnail extactor! */ - mime = EXTRACTOR_extractLast(EXTRACTOR_MIMETYPE, - prev); - if (mime == NULL) - return prev; - j = 0; - while (whitelist[j] != NULL) { - if (0 == strcmp(whitelist[j], mime)) - break; - j++; - } - - if (whitelist[j] == NULL) - return prev; - - /* Determine image format to use */ - if (options == NULL) - colors = QImage::Format_Indexed8; - else - switch(atoi(options)) - { - case 1: - colors = QImage::Format_Mono; - break; - case 8: - colors = QImage::Format_Indexed8; - break; - case 16: - case 24: - colors = QImage::Format_RGB32; - break; - default: - colors = QImage::Format_ARGB32; - break; - } - -#ifdef HAVE_QT_SVG - if (strcmp(mime, "image/svg+xml") == 0) - { - /* Render SVG image */ - QSvgRenderer svg; - QSize size; - - if (! svg.load(QByteArray((const char *) data))) - return prev; - - size = svg.defaultSize(); - img = new QImage(size, QImage::Format_ARGB32); - - QPainter painter(img); - painter.setViewport(0, 0, size.width(), size.height()); - painter.eraseRect(0, 0, size.width(), size.height()); - - svg.render(&painter); - } - else -#endif - { - /* Load image */ - img = new QImage(); - img->loadFromData(data, size); - } - - height = img->height(); - width = img->width(); - format = (char *) malloc(64); - snprintf(format, - 64, - "%ux%u", - (unsigned int) width, - (unsigned int) height); - prev = addKeyword(EXTRACTOR_SIZE, - format, - prev); - if (height == 0) - height = 1; - if (width == 0) - width = 1; - - /* Change color depth */ - QImage thumb = img->convertToFormat(colors); - delete img; - - /* Resize image - * - * Qt's scaled() produces poor quality if the image is resized to less than - * half the size. Therefore, we resize the image in multiple steps. - * http://lists.trolltech.com/qt-interest/2006-04/msg00376.html */ - while(true) - { - width /= 2; - if (width < THUMBSIZE) - width = THUMBSIZE; - - height /= 2; - if (height < THUMBSIZE) - height = THUMBSIZE; - - thumb = thumb.scaled(width, height, Qt::KeepAspectRatio, - Qt::SmoothTransformation); - - if (width == THUMBSIZE && height == THUMBSIZE) - break; - } - - buffer.setBuffer(&bytes); - buffer.open(QIODevice::WriteOnly); - thumb.save(&buffer, "PNG"); - - binary - = EXTRACTOR_binaryEncode((const unsigned char*) bytes.data(), - bytes.length()); - - if (binary == NULL) - return prev; - - return addKeyword(EXTRACTOR_THUMBNAIL_DATA, - binary, - prev); -} - -/* create new thread for C++ code (see Mantis #905) */ - -struct X { - const unsigned char * data; - size_t size; - struct EXTRACTOR_Keywords * prev; - const char * options; -}; - -static void * run(void * arg) { - struct X * x = (struct X*) arg; - return extract(x->data, x->size, x->prev, - x->options); -} - -struct EXTRACTOR_Keywords * -libextractor_thumbnailqt_extract(const char * filename, - const unsigned char * data, - size_t size, - struct EXTRACTOR_Keywords * prev, - const char * options) { - pthread_t pt; - struct X cls; - - void * ret; - cls.data = data; - cls.size = size; - cls.prev = prev; - cls.options = options; - if (0 == pthread_create(&pt, NULL, &run, &cls)) - if (0 == pthread_join(pt, &ret)) - return (struct EXTRACTOR_Keywords*) ret; - return prev; -} - - -struct EXTRACTOR_Keywords * -libextractor_thumbnail_extract(const char * filename, - const unsigned char * data, - size_t size, - struct EXTRACTOR_Keywords * prev, - const char * options) { - return libextractor_thumbnailqt_extract(filename, - data, - size, - prev, - options); -} - -} // extern "C" - -/* end of thumbnailextractorqt.cc */ diff --git a/src/plugins/thumbnailffmpeg/Makefile.am b/src/plugins/thumbnailffmpeg/Makefile.am deleted file mode 100644 index 8d1684e..0000000 --- a/src/plugins/thumbnailffmpeg/Makefile.am +++ /dev/null @@ -1,41 +0,0 @@ -include ../Makefile-plugins.am - -plugin_LTLIBRARIES = \ - libextractor_thumbnailffmpeg.la - -libextractor_thumbnailffmpeg_la_SOURCES = \ - thumbnailextractorffmpeg.c -libextractor_thumbnailffmpeg_la_LIBADD = \ - $(top_builddir)/src/main/libextractor.la \ - ../ffmpeg/libavformat/libavformat.a \ - ../ffmpeg/libavcodec/libavcodec.a \ - ../ffmpeg/libavutil/libavutil.a \ - ../ffmpeg/libswscale/libswscale.a \ - -lz -lbz2 -libextractor_thumbnailffmpeg_la_LDFLAGS = \ - $(PLUGINFLAGS) $(retaincommand) -libextractor_thumbnailffmpeg_la_CPPFLAGS = \ - -I$(top_scrdir)/include \ - -I../ffmpeg \ - -I../ffmpeg/libavformat \ - -I../ffmpeg/libavcodec \ - -I../ffmpeg/libavutil \ - -I../ffmpeg/libswscale - -../ffmpeg/libavformat/libavformat.a: Makefile - cd ../ffmpeg && $(MAKE) $(AM_MAKEFLAGS) all -../ffmpeg/libavcodec/libavcodec.a: Makefile - cd ../ffmpeg && $(MAKE) $(AM_MAKEFLAGS) all -../ffmpeg/libavutil/libavutil.a: Makefile - cd ../ffmpeg && $(MAKE) $(AM_MAKEFLAGS) all -../ffmpeg/libswscale/libswscale.a: Makefile - cd ../ffmpeg && $(MAKE) $(AM_MAKEFLAGS) all - -clean-local: - cd ../ffmpeg && $(MAKE) $(AM_MAKEFLAGS) clean -distclean-local: - cd ../ffmpeg && $(MAKE) $(AM_MAKEFLAGS) distclean - -dist-hook: clean-local - - diff --git a/src/plugins/thumbnailffmpeg/README b/src/plugins/thumbnailffmpeg/README deleted file mode 100644 index 297adc8..0000000 --- a/src/plugins/thumbnailffmpeg/README +++ /dev/null @@ -1,105 +0,0 @@ -This is a thumbnail extractor using the ffmpeg libraries that will eventually -support extracting thumbnails from both image and video files. Compiling -the ffmpeg libraries requires at least GNU make version 3.81. - -A local ffmpeg tree is used, because -(1) there are no recent official releases of the ffmpeg libs, -(2) mainline ffmpeg is not reentrant, -(3) security issues can be handled locally. - -Originally: -svn export -r 13836 --ignore-externals svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg -svn export -r 27100 svn://svn.mplayerhq.hu/mplayer/trunk/libswscale ffmpeg/libswscale -sync with ffmpeg: -FFREV=14311 -SWSREV=27332 -cd /tmp -svn co -r $FFREV --ignore-externals svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg -svn co -r $SWSREV svn://svn.mplayerhq.hu/mplayer/trunk/libswscale ffmpeg/libswscale -cd Extractor/src/plugins/thumbnailffmpeg -# copy, rsync skips .svn dirs -rsync -aC ffmpeg /tmp/ -cd /tmp/ffmpeg -svn update - -cd Extractor/src/plugins/thumbnailffmpeg -rsync -aC /tmp/ffmpeg . -# check for deletions -diff -qr . /tmp/ffmpeg -x .svn - -# check for additions - - -update ffmpeg_distfiles.am: -svn list -R src/plugins/ffmpeg | \ - sed '/\/$/d' | \ - sed '$!s/$/ \\/g' | \ - sed 's/^/ffmpeg\//' | \ - grep -v "no-indent" | \ - sed '1 i EXTRA_DIST = \\' > src/plugins/ffmpeg_distfiles.am - -Plan: test & enable ffmpeg decoders one by one -tests: -- multithreading test -- zzuf test -- random input test -(- valgrind) - -At least, the following should be eventually enabled: -if ! ./configure \ - --prefix=/tmp/FF \ - --disable-mmx \ - --disable-altivec \ - --enable-shared \ - --enable-swscale \ - --enable-gpl \ - --disable-vhook \ - --disable-postproc \ - --disable-network \ - --disable-ffmpeg \ - --disable-ffserver \ - --disable-ffplay \ - --disable-devices \ - --disable-protocols \ - --disable-bsfs \ - --disable-parsers \ - --disable-muxers \ - --disable-demuxers \ - --disable-encoders \ - --disable-decoders \ - --enable-parser=h263 \ - --enable-parser=h264 \ - --enable-parser=mjpeg \ - --enable-parser=mpeg4video \ - --enable-parser=mpegvideo \ - --enable-encoder=png \ - --enable-encoder=mjpeg \ - --enable-decoder=bmp \ - --enable-decoder=pcx \ - --enable-decoder=png \ - --enable-decoder=mjpeg \ - --enable-decoder=mjpegb \ - --enable-decoder=targa \ - --enable-decoder=tiff \ - --enable-decoder=flashsv \ - --enable-decoder=h263 \ - --enable-decoder=flv \ - --enable-decoder=h264 \ - --enable-decoder=mpeg1video \ - --enable-decoder=mpeg2video \ - --enable-decoder=mpegvideo \ - --enable-decoder=mpeg4 \ - --enable-decoder=vp6 \ - --enable-decoder=vp6a \ - --enable-decoder=vp6f \ - --enable-demuxer=asf \ - --enable-demuxer=avi \ - --enable-demuxer=flv \ - --enable-demuxer=mjpeg \ - --enable-demuxer=mpegps \ - --enable-demuxer=mpegts \ - --enable-demuxer=mpegvideo \ - --enable-demuxer=mov \ - --enable-demuxer=ogg \ - --enable-demuxer=rm - diff --git a/src/plugins/thumbnailffmpeg/thumbnailextractorffmpeg.c b/src/plugins/thumbnailffmpeg/thumbnailextractorffmpeg.c deleted file mode 100644 index 62f437d..0000000 --- a/src/plugins/thumbnailffmpeg/thumbnailextractorffmpeg.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - This file is part of libextractor. - Copyright (C) 2008 Heikki Lindholm - - 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 - 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 thumbnailextractorffmpeg.c - * @author Heikki Lindholm - * @brief this extractor produces a binary encoded - * thumbnail of images and videos using the ffmpeg libs. - */ - -#include "platform.h" -#include "extractor.h" - -#include -#include -#include - -#define DEBUG 0 - -struct StreamDescriptor -{ - const uint8_t *data; - size_t offset; - size_t size; -}; - - -void __attribute__ ((constructor)) ffmpeg_lib_init (void) -{ -#if DEBUG - printf ("av_register_all()\n"); -#endif - av_register_all (); -} - -static int -stream_read (void *opaque, uint8_t * buf, int buf_size) -{ - struct StreamDescriptor *rs = (struct StreamDescriptor *) opaque; - size_t len; -#if DEBUG - printf ("read_packet: %zu\n", buf_size); -#endif - if (rs) - { - if (rs->data == NULL) - return -1; - if (rs->offset >= rs->size) - return 0; - len = buf_size; - if (rs->offset + len > rs->size) - len = rs->size - rs->offset; - - memcpy (buf, rs->data + rs->offset, len); - rs->offset += len; -#if DEBUG - printf ("read_packet: len: %zu\n", len); -#endif - return len; - } - return -1; -} - -static offset_t -stream_seek (void *opaque, offset_t offset, int whence) -{ - struct StreamDescriptor *rs = (struct StreamDescriptor *) opaque; - offset_t off_abs; -#if DEBUG - printf ("my_seek: %lld %d\n", offset, whence); -#endif - if (rs) - { - if (whence == AVSEEK_SIZE) - return (offset_t) rs->size; - else if (whence == SEEK_CUR) - off_abs = (offset_t) rs->offset + offset; - else if (whence == SEEK_SET) - off_abs = offset; - else if (whence == SEEK_END) - off_abs = (offset_t) rs->size + offset; - else - { - printf ("whence error %d\n", whence); - abort (); - return AVERROR (EINVAL); - } - if (off_abs >= 0 && off_abs < (offset_t) rs->size) - rs->offset = (size_t) off_abs; - else - off_abs = AVERROR (EINVAL); - return off_abs; - } - return -1; -} - -static EXTRACTOR_KeywordList * -addKeyword (EXTRACTOR_KeywordType type, - char *keyword, EXTRACTOR_KeywordList * next) -{ - EXTRACTOR_KeywordList *result; - - if (keyword == NULL) - return next; - result = malloc (sizeof (EXTRACTOR_KeywordList)); - result->next = next; - result->keyword = keyword; - result->keywordType = type; - return result; -} - - -struct MimeToDecoderMapping -{ - const char *mime_type; - enum CodecID codec_id; -}; - -/* map mime image types to a decoder */ -static const struct MimeToDecoderMapping m2d_map[] = { - {"image/x-bmp", CODEC_ID_BMP}, - {"image/gif", CODEC_ID_GIF}, - {"image/jpeg", CODEC_ID_MJPEG}, - {"image/png", CODEC_ID_PNG}, - {"image/x-portable-pixmap", CODEC_ID_PPM}, - {NULL, CODEC_ID_NONE} -}; - -#define PROBE_MAX (1<<20) -#define BIOBUF_SIZE (64*1024) -#define THUMBSIZE 128 /* max dimension in pixels */ -#define MAX_THUMB_SIZE (100*1024) /* in bytes */ - -struct EXTRACTOR_Keywords * -libextractor_thumbnailffmpeg_extract (const char *filename, - const unsigned char *data, - size_t size, - struct EXTRACTOR_Keywords *prev) -{ - int score; - - AVInputFormat *fmt; - AVProbeData pdat; - - ByteIOContext *bio_ctx = NULL; - uint8_t *bio_buffer; - struct StreamDescriptor reader_state; - - AVFormatContext *format_ctx = NULL; - AVCodecContext *codec_ctx = NULL; - AVPacket packet; - int video_stream_index; - AVCodec *codec; - AVFrame *frame = NULL; - AVFrame *thumb_frame = NULL; - int64_t ts; - - struct SwsContext *scaler_ctx; - int sws_flags = SWS_BILINEAR; - uint8_t *thumb_buffer; - int thumb_width, thumb_height; - int sar_num, sar_den; - - uint8_t *encoder_output_buffer; - size_t encoder_output_buffer_size; - AVCodecContext *enc_codec_ctx; - AVCodec *enc_codec; - - int i; - int err; - int frame_finished; - - char *binary; - const char *mime; - int is_image; - enum CodecID image_codec_id; - - bio_ctx = NULL; - bio_buffer = NULL; - format_ctx = NULL; - codec = NULL; - frame = NULL; - thumb_frame = NULL; - thumb_buffer = NULL; - scaler_ctx = NULL; - encoder_output_buffer = NULL; - enc_codec = NULL; - enc_codec_ctx = NULL; - - is_image = 0; - - mime = EXTRACTOR_extractLast (EXTRACTOR_MIMETYPE, prev); - if (mime != NULL) - { - i = 0; - while (m2d_map[i].mime_type != NULL) - { - if (!strcmp (m2d_map[i].mime_type, mime)) - { - is_image = 1; - image_codec_id = m2d_map[i].codec_id; - break; - } - i++; - } - } - -#if DEBUG - printf ("is_image: %d codec:%d\n", is_image, image_codec_id); -#endif - if (!is_image) - { - pdat.filename = filename; - pdat.buf = (unsigned char *) data; - pdat.buf_size = (size > PROBE_MAX) ? PROBE_MAX : size; - - fmt = av_probe_input_format (&pdat, 1); - if (fmt == NULL) - return prev; -#if DEBUG - printf ("format %p [%s] [%s]\n", fmt, fmt->name, fmt->long_name); -#endif - pdat.buf = (unsigned char *) data; - pdat.buf_size = size > PROBE_MAX ? PROBE_MAX : size; - score = fmt->read_probe (&pdat); -#if DEBUG - printf ("score: %d\n", score); -#endif - /*if (score < 50) return prev; */ - } - - if (is_image) - { - codec_ctx = avcodec_alloc_context (); - codec = avcodec_find_decoder (image_codec_id); - if (codec != NULL) - { - if (avcodec_open (codec_ctx, codec) != 0) - { -#if DEBUG - printf ("open codec failed\n"); -#endif - codec = NULL; - } - } - } - else - { - bio_ctx = malloc (sizeof (ByteIOContext)); - bio_buffer = malloc (BIOBUF_SIZE); - - reader_state.data = data; - reader_state.offset = 0; - reader_state.size = size; - - init_put_byte (bio_ctx, bio_buffer, - BIOBUF_SIZE, 0, &reader_state, - stream_read, NULL, stream_seek); - - fmt->flags |= AVFMT_NOFILE; - err = av_open_input_stream (&format_ctx, bio_ctx, "", fmt, NULL); - if (err < 0) - { -#if DEBUG - printf ("couldn't open input stream\n"); -#endif - goto out; - } - - err = av_find_stream_info (format_ctx); - if (err < 0) - { -#if DEBUG - printf ("couldn't find codec params\n"); -#endif - goto out; - } - - for (i = 0; i < format_ctx->nb_streams; i++) - { - codec_ctx = format_ctx->streams[i]->codec; - if (codec_ctx->codec_type == CODEC_TYPE_VIDEO) - { - video_stream_index = i; - codec = avcodec_find_decoder (codec_ctx->codec_id); - if (codec == NULL) - { -#if DEBUG - printf ("find_decoder failed\n"); -#endif - break; - } - err = avcodec_open (codec_ctx, codec); - if (err != 0) - { -#if DEBUG - printf ("failed to open codec\n"); -#endif - codec = NULL; - } - break; - } - } - } - - if (codec_ctx == NULL || codec == NULL) - { -#if DEBUG - printf ("failed to open codec"); -#endif - goto out; - } - frame = avcodec_alloc_frame (); - if (frame == NULL) - { -#if DEBUG - printf ("failed to alloc frame"); -#endif - goto out; - } - - if (!is_image) - { -#if DEBUG - printf ("duration: %lld\n", format_ctx->duration); - if (format_ctx->duration == AV_NOPTS_VALUE) - printf ("duration unknown\n"); -#endif - /* TODO: if duration is known seek to to some better place(?) */ - ts = 10; // s - ts = ts * AV_TIME_BASE; - err = av_seek_frame (format_ctx, -1, ts, 0); - if (err >= 0) - { - avcodec_flush_buffers (codec_ctx); - } -#if DEBUG - else - printf ("seeking failed %d\n", err); -#endif - } - - frame_finished = 0; - if (is_image) - { - avcodec_decode_video (codec_ctx, frame, &frame_finished, data, size); - } - else - { - while (1) - { - err = av_read_frame (format_ctx, &packet); - if (err < 0) - break; - if (packet.stream_index == video_stream_index) - { - avcodec_decode_video (codec_ctx, - frame, - &frame_finished, - packet.data, packet.size); - if (frame_finished && frame->key_frame) - { - av_free_packet (&packet); - break; - } - } - av_free_packet (&packet); - } - } - - if (!frame_finished || codec_ctx->width == 0 || codec_ctx->height == 0) - goto out; - - sar_num = codec_ctx->sample_aspect_ratio.num; - sar_den = codec_ctx->sample_aspect_ratio.den; - if (sar_num <= 0 || sar_den <= 0) - { - sar_num = 1; - sar_den = 1; - } - if ((codec_ctx->width * sar_num) / sar_den > codec_ctx->height) - { - thumb_width = THUMBSIZE; - thumb_height = (thumb_width * codec_ctx->height) / - ((codec_ctx->width * sar_num) / sar_den); - } - else - { - thumb_height = THUMBSIZE; - thumb_width = (thumb_height * - ((codec_ctx->width * sar_num) / sar_den)) / - codec_ctx->height; - } - if (thumb_width < 8) - thumb_width = 8; - if (thumb_height < 1) - thumb_height = 1; -#if DEBUG - printf ("thumb dim: %d %d\n", thumb_width, thumb_height); -#endif - - scaler_ctx = - sws_getContext (codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, - thumb_width, thumb_height, PIX_FMT_RGB24, sws_flags, NULL, - NULL, NULL); - if (scaler_ctx == NULL) - { -#if DEBUG - printf ("failed to alloc scaler\n"); -#endif - goto out; - } - thumb_frame = avcodec_alloc_frame (); - thumb_buffer = - av_malloc (avpicture_get_size (PIX_FMT_RGB24, thumb_width, thumb_height)); - if (thumb_frame == NULL || thumb_buffer == NULL) - { -#if DEBUG - printf ("failed to alloc thumb frame\n"); -#endif - goto out; - } - avpicture_fill ((AVPicture *) thumb_frame, thumb_buffer, - PIX_FMT_RGB24, thumb_width, thumb_height); - - sws_scale (scaler_ctx, - frame->data, frame->linesize, - 0, codec_ctx->height, thumb_frame->data, thumb_frame->linesize); - - encoder_output_buffer_size = MAX_THUMB_SIZE; - encoder_output_buffer = av_malloc (encoder_output_buffer_size); - if (encoder_output_buffer == NULL) - { -#if DEBUG - printf ("couldn't alloc encoder output buf\n"); -#endif - goto out; - } - - enc_codec = avcodec_find_encoder_by_name ("png"); - if (enc_codec == NULL) - { -#if DEBUG - printf ("couldn't find encoder\n"); -#endif - goto out; - } - enc_codec_ctx = avcodec_alloc_context (); - enc_codec_ctx->width = thumb_width; - enc_codec_ctx->height = thumb_height; - enc_codec_ctx->pix_fmt = PIX_FMT_RGB24; - - if (avcodec_open (enc_codec_ctx, enc_codec) < 0) - { -#if DEBUG - printf ("couldn't open encoder\n"); -#endif - enc_codec = NULL; - goto out; - } - - err = avcodec_encode_video (enc_codec_ctx, - encoder_output_buffer, - encoder_output_buffer_size, thumb_frame); - if (err <= 0) - goto out; - - binary = - EXTRACTOR_binaryEncode ((const unsigned char *) encoder_output_buffer, - err); - if (binary != NULL) - prev = addKeyword (EXTRACTOR_THUMBNAIL_DATA, binary, prev); - -out: - if (enc_codec != NULL) - avcodec_close (enc_codec_ctx); - if (enc_codec_ctx != NULL) - av_free (enc_codec_ctx); - if (encoder_output_buffer != NULL) - av_free (encoder_output_buffer); - if (scaler_ctx != NULL) - sws_freeContext(scaler_ctx); - if (codec != NULL) - avcodec_close (codec_ctx); - if (format_ctx != NULL) - av_close_input_file (format_ctx); - if (frame != NULL) - av_free (frame); - if (thumb_buffer != NULL) - av_free (thumb_buffer); - if (thumb_frame != NULL) - av_free (thumb_frame); - if (bio_ctx != NULL) - free (bio_ctx); - if (bio_buffer != NULL) - free (bio_buffer); - - return prev; -} - -struct EXTRACTOR_Keywords * -libextractor_thumbnail_extract (const char *filename, - const unsigned char *data, - size_t size, - struct EXTRACTOR_Keywords *prev, - const char *options) -{ - return libextractor_thumbnailffmpeg_extract (filename, data, size, prev); -} - -/* end of thumbnailextractorffmpeg.c */ diff --git a/src/plugins/thumbnailffmpeg_extractor.c b/src/plugins/thumbnailffmpeg_extractor.c new file mode 100644 index 0000000..7fbde2d --- /dev/null +++ b/src/plugins/thumbnailffmpeg_extractor.c @@ -0,0 +1,536 @@ +/* + This file is part of libextractor. + Copyright (C) 2008 Heikki Lindholm + + 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 + 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 thumbnailffmpeg_extractor.c + * @author Heikki Lindholm + * @brief this extractor produces a binary encoded + * thumbnail of images and videos using the ffmpeg libs. + */ + +/* This is a thumbnail extractor using the ffmpeg libraries that will eventually + support extracting thumbnails from both image and video files. + + Note that ffmpeg has a few issues: + (1) there are no recent official releases of the ffmpeg libs + (2) ffmpeg has a history of having security issues (parser is not robust) + + So this plugin cannot be recommended for system with high security + requirements. +*/ + +#include "platform.h" +#include "extractor.h" +#include +#include +#include + +#define DEBUG 0 + +struct StreamDescriptor +{ + const uint8_t *data; + size_t offset; + size_t size; +}; + + +void __attribute__ ((constructor)) ffmpeg_lib_init (void) +{ +#if DEBUG + printf ("av_register_all()\n"); +#endif + av_register_all (); +} + +static int +stream_read (void *opaque, uint8_t * buf, int buf_size) +{ + struct StreamDescriptor *rs = (struct StreamDescriptor *) opaque; + size_t len; +#if DEBUG + printf ("read_packet: %zu\n", buf_size); +#endif + if (rs) + { + if (rs->data == NULL) + return -1; + if (rs->offset >= rs->size) + return 0; + len = buf_size; + if (rs->offset + len > rs->size) + len = rs->size - rs->offset; + + memcpy (buf, rs->data + rs->offset, len); + rs->offset += len; +#if DEBUG + printf ("read_packet: len: %zu\n", len); +#endif + return len; + } + return -1; +} + +static offset_t +stream_seek (void *opaque, offset_t offset, int whence) +{ + struct StreamDescriptor *rs = (struct StreamDescriptor *) opaque; + offset_t off_abs; +#if DEBUG + printf ("my_seek: %lld %d\n", offset, whence); +#endif + if (rs) + { + if (whence == AVSEEK_SIZE) + return (offset_t) rs->size; + else if (whence == SEEK_CUR) + off_abs = (offset_t) rs->offset + offset; + else if (whence == SEEK_SET) + off_abs = offset; + else if (whence == SEEK_END) + off_abs = (offset_t) rs->size + offset; + else + { + printf ("whence error %d\n", whence); + abort (); + return AVERROR (EINVAL); + } + if (off_abs >= 0 && off_abs < (offset_t) rs->size) + rs->offset = (size_t) off_abs; + else + off_abs = AVERROR (EINVAL); + return off_abs; + } + return -1; +} + +static EXTRACTOR_KeywordList * +addKeyword (EXTRACTOR_KeywordType type, + char *keyword, EXTRACTOR_KeywordList * next) +{ + EXTRACTOR_KeywordList *result; + + if (keyword == NULL) + return next; + result = malloc (sizeof (EXTRACTOR_KeywordList)); + result->next = next; + result->keyword = keyword; + result->keywordType = type; + return result; +} + + +struct MimeToDecoderMapping +{ + const char *mime_type; + enum CodecID codec_id; +}; + +/* map mime image types to a decoder */ +static const struct MimeToDecoderMapping m2d_map[] = { + {"image/x-bmp", CODEC_ID_BMP}, + {"image/gif", CODEC_ID_GIF}, + {"image/jpeg", CODEC_ID_MJPEG}, + {"image/png", CODEC_ID_PNG}, + {"image/x-portable-pixmap", CODEC_ID_PPM}, + {NULL, CODEC_ID_NONE} +}; + +#define PROBE_MAX (1<<20) +#define BIOBUF_SIZE (64*1024) +#define THUMBSIZE 128 /* max dimension in pixels */ +#define MAX_THUMB_SIZE (100*1024) /* in bytes */ + +int +EXTRACTOR_thumbnailffmpeg_extract (const unsigned char *data, + size_t size, + EXTRACTOR_MetaDataProcessor proc, + void *proc_cls, + const char *options) +{ + int score; + AVInputFormat *fmt; + AVProbeData pdat; + ByteIOContext *bio_ctx = NULL; + uint8_t *bio_buffer; + struct StreamDescriptor reader_state; + AVFormatContext *format_ctx = NULL; + AVCodecContext *codec_ctx = NULL; + AVPacket packet; + int video_stream_index; + AVCodec *codec; + AVFrame *frame = NULL; + AVFrame *thumb_frame = NULL; + int64_t ts; + + struct SwsContext *scaler_ctx; + int sws_flags = SWS_BILINEAR; + uint8_t *thumb_buffer; + int thumb_width, thumb_height; + int sar_num, sar_den; + + uint8_t *encoder_output_buffer; + size_t encoder_output_buffer_size; + AVCodecContext *enc_codec_ctx; + AVCodec *enc_codec; + + int i; + int err; + int frame_finished; + + char *binary; + const char *mime; + int is_image; + enum CodecID image_codec_id; + + bio_ctx = NULL; + bio_buffer = NULL; + format_ctx = NULL; + codec = NULL; + frame = NULL; + thumb_frame = NULL; + thumb_buffer = NULL; + scaler_ctx = NULL; + encoder_output_buffer = NULL; + enc_codec = NULL; + enc_codec_ctx = NULL; + + is_image = 0; + + mime = EXTRACTOR_extractLast (EXTRACTOR_MIMETYPE, prev); + if (mime != NULL) + { + i = 0; + while (m2d_map[i].mime_type != NULL) + { + if (!strcmp (m2d_map[i].mime_type, mime)) + { + is_image = 1; + image_codec_id = m2d_map[i].codec_id; + break; + } + i++; + } + } + +#if DEBUG + printf ("is_image: %d codec:%d\n", is_image, image_codec_id); +#endif + if (!is_image) + { + pdat.filename = filename; + pdat.buf = (unsigned char *) data; + pdat.buf_size = (size > PROBE_MAX) ? PROBE_MAX : size; + + fmt = av_probe_input_format (&pdat, 1); + if (fmt == NULL) + return prev; +#if DEBUG + printf ("format %p [%s] [%s]\n", fmt, fmt->name, fmt->long_name); +#endif + pdat.buf = (unsigned char *) data; + pdat.buf_size = size > PROBE_MAX ? PROBE_MAX : size; + score = fmt->read_probe (&pdat); +#if DEBUG + printf ("score: %d\n", score); +#endif + /*if (score < 50) return prev; */ + } + + if (is_image) + { + codec_ctx = avcodec_alloc_context (); + codec = avcodec_find_decoder (image_codec_id); + if (codec != NULL) + { + if (avcodec_open (codec_ctx, codec) != 0) + { +#if DEBUG + printf ("open codec failed\n"); +#endif + codec = NULL; + } + } + } + else + { + bio_ctx = malloc (sizeof (ByteIOContext)); + bio_buffer = malloc (BIOBUF_SIZE); + + reader_state.data = data; + reader_state.offset = 0; + reader_state.size = size; + + init_put_byte (bio_ctx, bio_buffer, + BIOBUF_SIZE, 0, &reader_state, + stream_read, NULL, stream_seek); + + fmt->flags |= AVFMT_NOFILE; + err = av_open_input_stream (&format_ctx, bio_ctx, "", fmt, NULL); + if (err < 0) + { +#if DEBUG + printf ("couldn't open input stream\n"); +#endif + goto out; + } + + err = av_find_stream_info (format_ctx); + if (err < 0) + { +#if DEBUG + printf ("couldn't find codec params\n"); +#endif + goto out; + } + + for (i = 0; i < format_ctx->nb_streams; i++) + { + codec_ctx = format_ctx->streams[i]->codec; + if (codec_ctx->codec_type == CODEC_TYPE_VIDEO) + { + video_stream_index = i; + codec = avcodec_find_decoder (codec_ctx->codec_id); + if (codec == NULL) + { +#if DEBUG + printf ("find_decoder failed\n"); +#endif + break; + } + err = avcodec_open (codec_ctx, codec); + if (err != 0) + { +#if DEBUG + printf ("failed to open codec\n"); +#endif + codec = NULL; + } + break; + } + } + } + + if (codec_ctx == NULL || codec == NULL) + { +#if DEBUG + printf ("failed to open codec"); +#endif + goto out; + } + frame = avcodec_alloc_frame (); + if (frame == NULL) + { +#if DEBUG + printf ("failed to alloc frame"); +#endif + goto out; + } + + if (!is_image) + { +#if DEBUG + printf ("duration: %lld\n", format_ctx->duration); + if (format_ctx->duration == AV_NOPTS_VALUE) + printf ("duration unknown\n"); +#endif + /* TODO: if duration is known seek to to some better place(?) */ + ts = 10; // s + ts = ts * AV_TIME_BASE; + err = av_seek_frame (format_ctx, -1, ts, 0); + if (err >= 0) + { + avcodec_flush_buffers (codec_ctx); + } +#if DEBUG + else + printf ("seeking failed %d\n", err); +#endif + } + + frame_finished = 0; + if (is_image) + { + avcodec_decode_video (codec_ctx, frame, &frame_finished, data, size); + } + else + { + while (1) + { + err = av_read_frame (format_ctx, &packet); + if (err < 0) + break; + if (packet.stream_index == video_stream_index) + { + avcodec_decode_video (codec_ctx, + frame, + &frame_finished, + packet.data, packet.size); + if (frame_finished && frame->key_frame) + { + av_free_packet (&packet); + break; + } + } + av_free_packet (&packet); + } + } + + if (!frame_finished || codec_ctx->width == 0 || codec_ctx->height == 0) + goto out; + + sar_num = codec_ctx->sample_aspect_ratio.num; + sar_den = codec_ctx->sample_aspect_ratio.den; + if (sar_num <= 0 || sar_den <= 0) + { + sar_num = 1; + sar_den = 1; + } + if ((codec_ctx->width * sar_num) / sar_den > codec_ctx->height) + { + thumb_width = THUMBSIZE; + thumb_height = (thumb_width * codec_ctx->height) / + ((codec_ctx->width * sar_num) / sar_den); + } + else + { + thumb_height = THUMBSIZE; + thumb_width = (thumb_height * + ((codec_ctx->width * sar_num) / sar_den)) / + codec_ctx->height; + } + if (thumb_width < 8) + thumb_width = 8; + if (thumb_height < 1) + thumb_height = 1; +#if DEBUG + printf ("thumb dim: %d %d\n", thumb_width, thumb_height); +#endif + + scaler_ctx = + sws_getContext (codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, + thumb_width, thumb_height, PIX_FMT_RGB24, sws_flags, NULL, + NULL, NULL); + if (scaler_ctx == NULL) + { +#if DEBUG + printf ("failed to alloc scaler\n"); +#endif + goto out; + } + thumb_frame = avcodec_alloc_frame (); + thumb_buffer = + av_malloc (avpicture_get_size (PIX_FMT_RGB24, thumb_width, thumb_height)); + if (thumb_frame == NULL || thumb_buffer == NULL) + { +#if DEBUG + printf ("failed to alloc thumb frame\n"); +#endif + goto out; + } + avpicture_fill ((AVPicture *) thumb_frame, thumb_buffer, + PIX_FMT_RGB24, thumb_width, thumb_height); + + sws_scale (scaler_ctx, + frame->data, frame->linesize, + 0, codec_ctx->height, thumb_frame->data, thumb_frame->linesize); + + encoder_output_buffer_size = MAX_THUMB_SIZE; + encoder_output_buffer = av_malloc (encoder_output_buffer_size); + if (encoder_output_buffer == NULL) + { +#if DEBUG + printf ("couldn't alloc encoder output buf\n"); +#endif + goto out; + } + + enc_codec = avcodec_find_encoder_by_name ("png"); + if (enc_codec == NULL) + { +#if DEBUG + printf ("couldn't find encoder\n"); +#endif + goto out; + } + enc_codec_ctx = avcodec_alloc_context (); + enc_codec_ctx->width = thumb_width; + enc_codec_ctx->height = thumb_height; + enc_codec_ctx->pix_fmt = PIX_FMT_RGB24; + + if (avcodec_open (enc_codec_ctx, enc_codec) < 0) + { +#if DEBUG + printf ("couldn't open encoder\n"); +#endif + enc_codec = NULL; + goto out; + } + + err = avcodec_encode_video (enc_codec_ctx, + encoder_output_buffer, + encoder_output_buffer_size, thumb_frame); + if (err <= 0) + goto out; + + binary = + EXTRACTOR_binaryEncode ((const unsigned char *) encoder_output_buffer, + err); + if (binary != NULL) + prev = addKeyword (EXTRACTOR_THUMBNAIL_DATA, binary, prev); + +out: + if (enc_codec != NULL) + avcodec_close (enc_codec_ctx); + if (enc_codec_ctx != NULL) + av_free (enc_codec_ctx); + if (encoder_output_buffer != NULL) + av_free (encoder_output_buffer); + if (scaler_ctx != NULL) + sws_freeContext(scaler_ctx); + if (codec != NULL) + avcodec_close (codec_ctx); + if (format_ctx != NULL) + av_close_input_file (format_ctx); + if (frame != NULL) + av_free (frame); + if (thumb_buffer != NULL) + av_free (thumb_buffer); + if (thumb_frame != NULL) + av_free (thumb_frame); + if (bio_ctx != NULL) + free (bio_ctx); + if (bio_buffer != NULL) + free (bio_buffer); + + return prev; +} + +int +EXTRACTOR_thumbnail_extract (const unsigned char *data, + size_t size, + EXTRACTOR_MetaDataProcessor proc, + void *proc_cls, + const char *options) +{ + return EXTRACTOR_thumbnailffmpeg_extract (data, size, proc, proc_cls, options); +} + +/* end of thumbnailffmpeg_extractor.c */ -- cgit v1.2.3