libextractor

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

mediautil.c (7219B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2026 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  * @file plugins/mediautil.c
     22  * @brief helpers shared by the video thumbnail and audio preview plugins
     23  * @author Christian Grothoff
     24  */
     25 #include "platform.h"
     26 #include "mediautil.h"
     27 #include <magic.h>
     28 
     29 /**
     30  * How many bytes we give libmagic to make up its mind.
     31  */
     32 #define SNIFF_SIZE (16 * 1024)
     33 
     34 
     35 void
     36 EXTRACTOR_media_options_parse_ (const char *config,
     37                                 struct EXTRACTOR_MediaOptions *opt)
     38 {
     39   const char *pos;
     40 
     41   opt->size = 128;
     42   opt->png = 0;
     43   opt->offset = 30;
     44   opt->length = 15;
     45   opt->bitrate = 24000;
     46   opt->deadline = 10000;
     47   if (NULL == config)
     48     return;
     49   pos = config;
     50   while ('\0' != *pos)
     51   {
     52     unsigned long long v;
     53     char *endp;
     54 
     55     if (0 == strncmp (pos,
     56                       "format=",
     57                       strlen ("format=")))
     58     {
     59       pos += strlen ("format=");
     60       opt->png = (0 == strncmp (pos,
     61                                 "png",
     62                                 strlen ("png")));
     63     }
     64     else if (0 == strncmp (pos,
     65                            "size=",
     66                            strlen ("size=")))
     67     {
     68       pos += strlen ("size=");
     69       v = strtoull (pos, &endp, 10);
     70       if ( (endp != pos) &&
     71            (v >= 8) &&
     72            (v <= 1024) )
     73         opt->size = (unsigned int) v;
     74     }
     75     else if (0 == strncmp (pos,
     76                            "offset=",
     77                            strlen ("offset=")))
     78     {
     79       pos += strlen ("offset=");
     80       v = strtoull (pos, &endp, 10);
     81       if ( (endp != pos) &&
     82            (v <= 24 * 60 * 60) )
     83         opt->offset = (unsigned int) v;
     84     }
     85     else if (0 == strncmp (pos,
     86                            "length=",
     87                            strlen ("length=")))
     88     {
     89       pos += strlen ("length=");
     90       v = strtoull (pos, &endp, 10);
     91       if ( (endp != pos) &&
     92            (v >= 1) &&
     93            (v <= 60) )
     94         opt->length = (unsigned int) v;
     95     }
     96     else if (0 == strncmp (pos,
     97                            "bitrate=",
     98                            strlen ("bitrate=")))
     99     {
    100       pos += strlen ("bitrate=");
    101       v = strtoull (pos, &endp, 10);
    102       if ( (endp != pos) &&
    103            (v >= 6000) &&
    104            (v <= 128000) )
    105         opt->bitrate = (unsigned int) v;
    106     }
    107     else if (0 == strncmp (pos,
    108                            "deadline=",
    109                            strlen ("deadline=")))
    110     {
    111       pos += strlen ("deadline=");
    112       v = strtoull (pos, &endp, 10);
    113       if ( (endp != pos) &&
    114            (v >= 100) &&
    115            (v <= 120000) )
    116         opt->deadline = (unsigned int) v;
    117     }
    118     /* advance to the next assignment */
    119     pos = strchr (pos, ',');
    120     if (NULL == pos)
    121       break;
    122     pos++;
    123   }
    124 }
    125 
    126 
    127 int
    128 EXTRACTOR_media_is_media_ (struct EXTRACTOR_ExtractContext *ec,
    129                            int want_audio)
    130 {
    131   magic_t magic;
    132   void *data;
    133   ssize_t iret;
    134   const char *mime;
    135   int ret;
    136 
    137   if (-1 == (iret = ec->read (ec->cls,
    138                               &data,
    139                               SNIFF_SIZE)))
    140     return 0;
    141   ret = 0;
    142   if (NULL == (magic = magic_open (MAGIC_MIME_TYPE)))
    143     return 0;
    144   if (0 == magic_load (magic, NULL))
    145   {
    146     mime = magic_buffer (magic,
    147                          data,
    148                          iret);
    149     if (NULL != mime)
    150     {
    151       if (0 == strncmp (mime,
    152                         "video/",
    153                         strlen ("video/")))
    154         ret = 1;
    155       if ( (0 != want_audio) &&
    156            (0 == strncmp (mime,
    157                           "audio/",
    158                           strlen ("audio/"))) )
    159         ret = 1;
    160       /* Ogg and Matroska files carrying video are frequently reported as
    161          "application/ogg" or "video/x-matroska"; the former would be lost
    162          here, so let it through and let the demuxer decide. */
    163       if (0 == strcmp (mime,
    164                        "application/ogg"))
    165         ret = 1;
    166     }
    167   }
    168   magic_close (magic);
    169   if (0 != ec->seek (ec->cls,
    170                      0,
    171                      SEEK_SET))
    172     return 0;
    173   return ret;
    174 }
    175 
    176 
    177 /**
    178  * Current time in milliseconds since an arbitrary epoch.
    179  *
    180  * @return the time
    181  */
    182 static uint64_t
    183 now_ms (void)
    184 {
    185   struct timespec ts;
    186 
    187   if (0 != clock_gettime (CLOCK_MONOTONIC,
    188                           &ts))
    189     return 0;
    190   return ((uint64_t) ts.tv_sec) * 1000ULL
    191          + ((uint64_t) ts.tv_nsec) / 1000000ULL;
    192 }
    193 
    194 
    195 void
    196 EXTRACTOR_media_deadline_start_ (struct EXTRACTOR_MediaDeadline *dl,
    197                                  unsigned int ms)
    198 {
    199   dl->expiration = now_ms () + ms;
    200 }
    201 
    202 
    203 int
    204 EXTRACTOR_media_deadline_expired_ (const struct EXTRACTOR_MediaDeadline *dl)
    205 {
    206   return now_ms () >= dl->expiration;
    207 }
    208 
    209 
    210 uint64_t
    211 EXTRACTOR_media_deadline_remaining_ (const struct EXTRACTOR_MediaDeadline *dl)
    212 {
    213   uint64_t now = now_ms ();
    214 
    215   if (now >= dl->expiration)
    216     return 0;
    217   return dl->expiration - now;
    218 }
    219 
    220 
    221 int
    222 EXTRACTOR_media_thumbnail_size_ (unsigned int width,
    223                                  unsigned int height,
    224                                  unsigned int box,
    225                                  unsigned int *rwidth,
    226                                  unsigned int *rheight)
    227 {
    228   uint64_t w = width;
    229   uint64_t h = height;
    230 
    231   if ( (0 == width) ||
    232        (0 == height) ||
    233        (width > EXTRACTOR_MEDIA_MAX_DIMENSION) ||
    234        (height > EXTRACTOR_MEDIA_MAX_DIMENSION) ||
    235        (((uint64_t) width) * height > EXTRACTOR_MEDIA_MAX_PIXELS) )
    236     return 0;
    237   if (h > box)
    238   {
    239     w = w * box / h;
    240     h = box;
    241   }
    242   if (w > box)
    243   {
    244     h = h * box / w;
    245     w = box;
    246   }
    247   if ( (0 == w) ||
    248        (0 == h) )
    249     return 0;
    250   /* many encoders dislike odd dimensions, and we lose nothing by rounding */
    251   w &= ~1ULL;
    252   h &= ~1ULL;
    253   if ( (0 == w) ||
    254        (0 == h) )
    255     return 0;
    256   *rwidth = (unsigned int) w;
    257   *rheight = (unsigned int) h;
    258   return 1;
    259 }
    260 
    261 
    262 void
    263 EXTRACTOR_media_fade_s16_ (int16_t *samples,
    264                            size_t num_samples,
    265                            size_t fade_samples)
    266 {
    267   size_t i;
    268 
    269   if (0 == fade_samples)
    270     return;
    271   if (fade_samples * 2 > num_samples)
    272     fade_samples = num_samples / 2;
    273   for (i = 0; i < fade_samples; i++)
    274   {
    275     samples[i] = (int16_t) (((int32_t) samples[i]) * (int32_t) i
    276                             / (int32_t) fade_samples);
    277     samples[num_samples - 1 - i] =
    278       (int16_t) (((int32_t) samples[num_samples - 1 - i]) * (int32_t) i
    279                  / (int32_t) fade_samples);
    280   }
    281 }
    282 
    283 
    284 /* end of mediautil.c */