libextractor

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

mpeg_extractor.c (5506B)


      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       if (0 == mime)
    110       {
    111         mime = 1;
    112         ADD ("video/mpeg",
    113              EXTRACTOR_METATYPE_MIMETYPE);
    114       }
    115       snprintf (format,
    116                 sizeof(format), "%ux%u",
    117                 info->sequence->width, info->sequence->height);
    118       if (0 != strcmp (lformat,
    119                        format))
    120       {
    121         strcpy (lformat,
    122                 format);
    123         ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS);
    124       }
    125       switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED)
    126       {
    127       case SEQ_VIDEO_FORMAT_PAL:
    128         if (0 == fpal)
    129         {
    130           fpal = 1;
    131           ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    132         }
    133         break;
    134       case SEQ_VIDEO_FORMAT_NTSC:
    135         if (0 == fntsc)
    136         {
    137           fntsc = 1;
    138           ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    139         }
    140         break;
    141       case SEQ_VIDEO_FORMAT_SECAM:
    142         if (0 == fsecam)
    143         {
    144           fsecam = 1;
    145           ADD ("SECAM", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    146         }
    147         break;
    148       case SEQ_VIDEO_FORMAT_MAC:
    149         if (0 == fmac)
    150         {
    151           fmac = 1;
    152           ADD ("MAC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    153         }
    154         break;
    155       default:
    156         break;
    157       }
    158       if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0)
    159       {
    160         if (0 == fmt1)
    161         {
    162           fmt1 = 1;
    163           ADD ("MPEG2", EXTRACTOR_METATYPE_FORMAT_VERSION);
    164         }
    165       }
    166       else
    167       {
    168         if (0 == fmt2)
    169         {
    170           fmt2 = 1;
    171           ADD ("MPEG1", EXTRACTOR_METATYPE_FORMAT_VERSION);
    172         }
    173       }
    174       if ( (0 == did_seek) &&
    175            (fsize != -1) &&
    176            (fsize > 1024 * 256 * 2) )
    177       {
    178         /* skip to the end of the mpeg for speed */
    179         did_seek = 1;
    180         ec->seek (ec->cls,
    181                   fsize - 256 * 1024,
    182                   SEEK_SET);
    183       }
    184       break;
    185     case STATE_GOP:
    186       fail_count = 0;
    187       if ( (NULL != info->gop) &&
    188            (0 != info->gop->pictures) )
    189       {
    190         snprintf (gop_format,
    191                   sizeof (gop_format),
    192                   "%02u:%02u:%02u (%u frames)",
    193                   info->gop->hours,
    194                   info->gop->minutes,
    195                   info->gop->seconds,
    196                   info->gop->pictures);
    197         have_gop = 1;
    198       }
    199       break;
    200     case STATE_SLICE:
    201       fail_count = 0;
    202       break;
    203     case STATE_END:
    204       fail_count = 0;
    205       break;
    206     case STATE_INVALID:
    207       goto EXIT;
    208     default:
    209       break;
    210     }
    211   }
    212 EXIT:
    213   if (1 == have_gop)
    214     ADD (gop_format, EXTRACTOR_METATYPE_DURATION);
    215   mpeg2_close (handle);
    216 }
    217 
    218 
    219 /* end of mpeg_extractor.c */