libextractor

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

mpeg_extractor.c (5537B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian Grothoff
      4 
      5      libextractor is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      libextractor is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libextractor; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19  */
     20 
     21 /**
     22  * @file plugins/mpeg_extractor.c
     23  * @brief plugin to support MPEG files
     24  * @author Christian Grothoff
     25  */
     26 #include "platform.h"
     27 #include "extractor.h"
     28 #include <mpeg2dec/mpeg2.h>
     29 
     30 
     31 /**
     32  * Give meta data to extractor.
     33  *
     34  * @param t type of the meta data
     35  * @param s meta data value in utf8 format
     36  */
     37 #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "mpeg", t, \
     38                                          EXTRACTOR_METAFORMAT_UTF8, \
     39                                          "text/plain", s, strlen (s) \
     40                                          + 1)) goto EXIT; \
     41 } while (0)
     42 
     43 
     44 /**
     45  * Main entry method for the 'video/mpeg' extraction plugin.
     46  *
     47  * @param ec extraction context provided to the plugin
     48  */
     49 void
     50 EXTRACTOR_mpeg_extract_method (struct EXTRACTOR_ExtractContext *ec)
     51 {
     52   mpeg2dec_t *handle;
     53   const mpeg2_info_t *info;
     54   void *buf;
     55   ssize_t avail;
     56   mpeg2_state_t state;
     57   char format[256];
     58   char lformat[256];
     59   char gop_format[256];
     60   int have_gop;
     61   uint64_t fsize;
     62   unsigned int fail_count;
     63   int did_seek;
     64   int fmt1;
     65   int fmt2;
     66   int mime;
     67   int fpal;
     68   int fntsc;
     69   int fsecam;
     70   int fmac;
     71 
     72   if (NULL == (handle = mpeg2_init ()))
     73     return;
     74   if (NULL == (info = mpeg2_info (handle)))
     75   {
     76     mpeg2_close (handle);
     77     return;
     78   }
     79   fsize = ec->get_size (ec->cls);
     80   buf = NULL;
     81   have_gop = 0;
     82   fail_count = 0;
     83   did_seek = 0;
     84   fmt1 = 0;
     85   fmt2 = 0;
     86   mime = 0;
     87   fpal = 0;
     88   fntsc = 0;
     89   fsecam = 0;
     90   fmac = 0;
     91   lformat[0] = '\0';
     92   while (1)
     93   {
     94     state = mpeg2_parse (handle);
     95     switch (state)
     96     {
     97     case STATE_BUFFER:
     98       if (fail_count > 16)
     99         goto EXIT; /* do not read large non-mpeg files */
    100       fail_count++;
    101       if (0 >= (avail = ec->read (ec->cls,
    102                                   &buf,
    103                                   16 * 1024)))
    104         goto EXIT;
    105       mpeg2_buffer (handle, buf, buf + avail);
    106       break;
    107     case STATE_SEQUENCE:
    108       fail_count = 0;
    109       format[0] = fsize;
    110       format[0]++;
    111       if (0 == mime)
    112       {
    113         mime = 1;
    114         ADD ("video/mpeg", EXTRACTOR_METATYPE_MIMETYPE);
    115       }
    116       snprintf (format,
    117                 sizeof(format), "%ux%u",
    118                 info->sequence->width, info->sequence->height);
    119       if (0 != strcmp (lformat,
    120                        format))
    121       {
    122         strcpy (lformat,
    123                 format);
    124         ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS);
    125       }
    126       switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED)
    127       {
    128       case SEQ_VIDEO_FORMAT_PAL:
    129         if (0 == fpal)
    130         {
    131           fpal = 1;
    132           ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    133         }
    134         break;
    135       case SEQ_VIDEO_FORMAT_NTSC:
    136         if (0 == fntsc)
    137         {
    138           fntsc = 1;
    139           ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    140         }
    141         break;
    142       case SEQ_VIDEO_FORMAT_SECAM:
    143         if (0 == fsecam)
    144         {
    145           fsecam = 1;
    146           ADD ("SECAM", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    147         }
    148         break;
    149       case SEQ_VIDEO_FORMAT_MAC:
    150         if (0 == fmac)
    151         {
    152           fmac = 1;
    153           ADD ("MAC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    154         }
    155         break;
    156       default:
    157         break;
    158       }
    159       if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0)
    160       {
    161         if (0 == fmt1)
    162         {
    163           fmt1 = 1;
    164           ADD ("MPEG2", EXTRACTOR_METATYPE_FORMAT_VERSION);
    165         }
    166       }
    167       else
    168       {
    169         if (0 == fmt2)
    170         {
    171           fmt2 = 1;
    172           ADD ("MPEG1", EXTRACTOR_METATYPE_FORMAT_VERSION);
    173         }
    174       }
    175       if ( (0 == did_seek) &&
    176            (fsize != -1) &&
    177            (fsize > 1024 * 256 * 2) )
    178       {
    179         /* skip to the end of the mpeg for speed */
    180         did_seek = 1;
    181         ec->seek (ec->cls,
    182                   fsize - 256 * 1024,
    183                   SEEK_SET);
    184       }
    185       break;
    186     case STATE_GOP:
    187       fail_count = 0;
    188       if ( (NULL != info->gop) &&
    189            (0 != info->gop->pictures) )
    190       {
    191         snprintf (gop_format,
    192                   sizeof (gop_format),
    193                   "%02u:%02u:%02u (%u frames)",
    194                   info->gop->hours,
    195                   info->gop->minutes,
    196                   info->gop->seconds,
    197                   info->gop->pictures);
    198         have_gop = 1;
    199       }
    200       break;
    201     case STATE_SLICE:
    202       fail_count = 0;
    203       break;
    204     case STATE_END:
    205       fail_count = 0;
    206       break;
    207     case STATE_INVALID:
    208       goto EXIT;
    209     default:
    210       break;
    211     }
    212   }
    213 EXIT:
    214   if (1 == have_gop)
    215     ADD (gop_format, EXTRACTOR_METATYPE_DURATION);
    216   mpeg2_close (handle);
    217 }
    218 
    219 
    220 /* end of mpeg_extractor.c */