"Fossies" - the Fresh Open Source Software Archive

Member "minidlna-1.3.0/metadata.c" (24 Nov 2020, 45239 Bytes) of package /linux/privat/minidlna-1.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "metadata.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.2.1_vs_1.3.0.

    1 /* MiniDLNA media server
    2  * Copyright (C) 2008-2017  Justin Maggard
    3  *
    4  * This file is part of MiniDLNA.
    5  *
    6  * MiniDLNA is free software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License version 2 as
    8  * published by the Free Software Foundation.
    9  *
   10  * MiniDLNA is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
   17  */
   18 #include "config.h"
   19 
   20 #include <stdio.h>
   21 #include <ctype.h>
   22 #include <string.h>
   23 #include <stdlib.h>
   24 #include <libgen.h>
   25 #include <unistd.h>
   26 #include <sys/stat.h>
   27 #include <sys/types.h>
   28 #include <sys/param.h>
   29 #include <fcntl.h>
   30 
   31 #include <libexif/exif-loader.h>
   32 #include <jpeglib.h>
   33 #include <setjmp.h>
   34 #include "libav.h"
   35 
   36 #include "upnpglobalvars.h"
   37 #include "tagutils/tagutils.h"
   38 #include "image_utils.h"
   39 #include "upnpreplyparse.h"
   40 #include "tivo_utils.h"
   41 #include "metadata.h"
   42 #include "albumart.h"
   43 #include "utils.h"
   44 #include "sql.h"
   45 #include "log.h"
   46 
   47 #define FLAG_TITLE  0x00000001
   48 #define FLAG_ARTIST 0x00000002
   49 #define FLAG_ALBUM  0x00000004
   50 #define FLAG_GENRE  0x00000008
   51 #define FLAG_COMMENT    0x00000010
   52 #define FLAG_CREATOR    0x00000020
   53 #define FLAG_DATE   0x00000040
   54 #define FLAG_DLNA_PN    0x00000080
   55 #define FLAG_MIME   0x00000100
   56 #define FLAG_DURATION   0x00000200
   57 #define FLAG_RESOLUTION 0x00000400
   58 
   59 /* Audio profile flags */
   60 enum audio_profiles {
   61     PROFILE_AUDIO_UNKNOWN,
   62     PROFILE_AUDIO_MP3,
   63     PROFILE_AUDIO_AC3,
   64     PROFILE_AUDIO_WMA_BASE,
   65     PROFILE_AUDIO_WMA_FULL,
   66     PROFILE_AUDIO_WMA_PRO,
   67     PROFILE_AUDIO_MP2,
   68     PROFILE_AUDIO_PCM,
   69     PROFILE_AUDIO_AAC,
   70     PROFILE_AUDIO_AAC_MULT5,
   71     PROFILE_AUDIO_AMR
   72 };
   73 
   74 /* This function shamelessly copied from libdlna */
   75 #define MPEG_TS_SYNC_CODE 0x47
   76 #define MPEG_TS_PACKET_LENGTH 188
   77 #define MPEG_TS_PACKET_LENGTH_DLNA 192 /* prepends 4 bytes to TS packet */
   78 int
   79 dlna_timestamp_is_present(const char *filename, int *raw_packet_size)
   80 {
   81     unsigned char buffer[3*MPEG_TS_PACKET_LENGTH_DLNA];
   82     int fd, i;
   83 
   84     /* read file header */
   85     fd = open(filename, O_RDONLY);
   86     if( fd < 0 )
   87         return 0;
   88     i = read(fd, buffer, MPEG_TS_PACKET_LENGTH_DLNA*3);
   89     close(fd);
   90     if( i < 0 )
   91         return 0;
   92     for( i = 0; i < MPEG_TS_PACKET_LENGTH_DLNA; i++ )
   93     {
   94         if( buffer[i] == MPEG_TS_SYNC_CODE )
   95         {
   96             if (buffer[i + MPEG_TS_PACKET_LENGTH_DLNA] == MPEG_TS_SYNC_CODE &&
   97                 buffer[i + MPEG_TS_PACKET_LENGTH_DLNA*2] == MPEG_TS_SYNC_CODE)
   98             {
   99                 *raw_packet_size = MPEG_TS_PACKET_LENGTH_DLNA;
  100                 if (buffer[i+MPEG_TS_PACKET_LENGTH] == 0x00 &&
  101                     buffer[i+MPEG_TS_PACKET_LENGTH+1] == 0x00 &&
  102                     buffer[i+MPEG_TS_PACKET_LENGTH+2] == 0x00 &&
  103                     buffer[i+MPEG_TS_PACKET_LENGTH+3] == 0x00)
  104                     return 0;
  105                 else
  106                     return 1;
  107             } else if (buffer[i + MPEG_TS_PACKET_LENGTH] == MPEG_TS_SYNC_CODE &&
  108                    buffer[i + MPEG_TS_PACKET_LENGTH*2] == MPEG_TS_SYNC_CODE) {
  109                 *raw_packet_size = MPEG_TS_PACKET_LENGTH;
  110                 return 0;
  111             }
  112         }
  113     }
  114     *raw_packet_size = 0;
  115     return 0;
  116 }
  117 
  118 void
  119 check_for_captions(const char *path, int64_t detailID)
  120 {
  121     char file[MAXPATHLEN];
  122     char *p;
  123     int ret;
  124 
  125     strncpyt(file, path, sizeof(file));
  126     p = strip_ext(file);
  127     if (!p)
  128         return;
  129 
  130     /* If we weren't given a detail ID, look for one. */
  131     if (!detailID)
  132     {
  133         detailID = sql_get_int64_field(db, "SELECT ID from DETAILS where (PATH > '%q.' and PATH <= '%q.z')"
  134                            " and MIME glob 'video/*' limit 1", file, file);
  135         if (detailID <= 0)
  136         {
  137             //DPRINTF(E_MAXDEBUG, L_METADATA, "No file found for caption %s.\n", path);
  138             return;
  139         }
  140     }
  141 
  142     strcpy(p, ".srt");
  143     ret = access(file, R_OK);
  144     if (ret != 0)
  145     {
  146         strcpy(p, ".smi");
  147         ret = access(file, R_OK);
  148     }
  149 
  150     if (ret == 0)
  151     {
  152         sql_exec(db, "INSERT OR REPLACE into CAPTIONS"
  153                      " (ID, PATH) "
  154                      "VALUES"
  155                      " (%lld, %Q)", detailID, file);
  156     }
  157 }
  158 
  159 static void
  160 parse_nfo(const char *path, metadata_t *m)
  161 {
  162     FILE *nfo;
  163     char *buf;
  164     struct NameValueParserData xml;
  165     struct stat file;
  166     size_t nread;
  167     char *val, *val2;
  168 
  169     if (stat(path, &file) != 0 ||
  170         file.st_size > 65535)
  171     {
  172         DPRINTF(E_INFO, L_METADATA, "Not parsing very large .nfo file %s\n", path);
  173         return;
  174     }
  175     DPRINTF(E_DEBUG, L_METADATA, "Parsing .nfo file: %s\n", path);
  176     buf = calloc(1, file.st_size + 1);
  177     if (!buf)
  178         return;
  179     nfo = fopen(path, "r");
  180     if (!nfo)
  181     {
  182         free(buf);
  183         return;
  184     }
  185     nread = fread(buf, 1, file.st_size, nfo);
  186     fclose(nfo);
  187     
  188     ParseNameValue(buf, nread, &xml, 0);
  189 
  190     //printf("\ttype: %s\n", GetValueFromNameValueList(&xml, "rootElement"));
  191     val = GetValueFromNameValueList(&xml, "title");
  192     if (val)
  193     {
  194         char *esc_tag, *title;
  195         val2 = GetValueFromNameValueList(&xml, "episodetitle");
  196         if (val2)
  197             xasprintf(&title, "%s - %s", val, val2);
  198         else
  199             title = strdup(val);
  200         esc_tag = unescape_tag(title, 1);
  201         m->title = escape_tag(esc_tag, 1);
  202         free(esc_tag);
  203         free(title);
  204     }
  205 
  206     val = GetValueFromNameValueList(&xml, "plot");
  207     if (val)
  208     {
  209         char *esc_tag = unescape_tag(val, 1);
  210         m->comment = escape_tag(esc_tag, 1);
  211         free(esc_tag);
  212     }
  213 
  214     val = GetValueFromNameValueList(&xml, "capturedate");
  215     if (val)
  216     {
  217         char *esc_tag = unescape_tag(val, 1);
  218         m->date = escape_tag(esc_tag, 1);
  219         free(esc_tag);
  220     }
  221 
  222     val = GetValueFromNameValueList(&xml, "genre");
  223     if (val)
  224     {
  225         char *esc_tag = unescape_tag(val, 1);
  226         free(m->genre);
  227         m->genre = escape_tag(esc_tag, 1);
  228         free(esc_tag);
  229     }
  230 
  231     val = GetValueFromNameValueList(&xml, "mime");
  232     if (val)
  233     {
  234         char *esc_tag = unescape_tag(val, 1);
  235         free(m->mime);
  236         m->mime = escape_tag(esc_tag, 1);
  237         free(esc_tag);
  238     }
  239 
  240     val = GetValueFromNameValueList(&xml, "season");
  241     if (val)
  242         m->disc = atoi(val);
  243 
  244     val = GetValueFromNameValueList(&xml, "episode");
  245     if (val)
  246         m->track = atoi(val);
  247 
  248     ClearNameValueList(&xml);
  249     free(buf);
  250 }
  251 
  252 void
  253 free_metadata(metadata_t *m, uint32_t flags)
  254 {
  255     if( flags & FLAG_TITLE )
  256         free(m->title);
  257     if( flags & FLAG_ARTIST )
  258         free(m->artist);
  259     if( flags & FLAG_ALBUM )
  260         free(m->album);
  261     if( flags & FLAG_GENRE )
  262         free(m->genre);
  263     if( flags & FLAG_CREATOR )
  264         free(m->creator);
  265     if( flags & FLAG_DATE )
  266         free(m->date);
  267     if( flags & FLAG_COMMENT )
  268         free(m->comment);
  269     if( flags & FLAG_DLNA_PN )
  270         free(m->dlna_pn);
  271     if( flags & FLAG_MIME )
  272         free(m->mime);
  273     if( flags & FLAG_DURATION )
  274         free(m->duration);
  275     if( flags & FLAG_RESOLUTION )
  276         free(m->resolution);
  277 }
  278 
  279 int64_t
  280 GetFolderMetadata(const char *name, const char *path, const char *artist, const char *genre, int64_t album_art)
  281 {
  282     int ret;
  283 
  284     ret = sql_exec(db, "INSERT into DETAILS"
  285                        " (TITLE, PATH, CREATOR, ARTIST, GENRE, ALBUM_ART) "
  286                        "VALUES"
  287                        " ('%q', %Q, %Q, %Q, %Q, %lld);",
  288                        name, path, artist, artist, genre, album_art);
  289     if( ret != SQLITE_OK )
  290         ret = 0;
  291     else
  292         ret = sqlite3_last_insert_rowid(db);
  293 
  294     return ret;
  295 }
  296 
  297 int64_t
  298 GetAudioMetadata(const char *path, const char *name)
  299 {
  300     char type[4];
  301     static char lang[6] = { '\0' };
  302     struct stat file;
  303     int64_t ret;
  304     char *esc_tag;
  305     int i;
  306     int64_t album_art = 0;
  307     struct song_metadata song;
  308     metadata_t m;
  309     uint32_t free_flags = FLAG_MIME|FLAG_DURATION|FLAG_DLNA_PN|FLAG_DATE;
  310     memset(&m, '\0', sizeof(metadata_t));
  311 
  312     if ( stat(path, &file) != 0 )
  313         return 0;
  314 
  315     if( ends_with(path, ".mp3") )
  316     {
  317         strcpy(type, "mp3");
  318         m.mime = strdup("audio/mpeg");
  319     }
  320     else if( ends_with(path, ".m4a") || ends_with(path, ".mp4") ||
  321              ends_with(path, ".aac") || ends_with(path, ".m4p") )
  322     {
  323         strcpy(type, "aac");
  324         m.mime = strdup("audio/mp4");
  325     }
  326     else if( ends_with(path, ".3gp") )
  327     {
  328         strcpy(type, "aac");
  329         m.mime = strdup("audio/3gpp");
  330     }
  331     else if( ends_with(path, ".wma") || ends_with(path, ".asf") )
  332     {
  333         strcpy(type, "asf");
  334         m.mime = strdup("audio/x-ms-wma");
  335     }
  336     else if( ends_with(path, ".flac") || ends_with(path, ".fla") || ends_with(path, ".flc") )
  337     {
  338         strcpy(type, "flc");
  339         m.mime = strdup("audio/x-flac");
  340     }
  341     else if( ends_with(path, ".wav") )
  342     {
  343         strcpy(type, "wav");
  344         m.mime = strdup("audio/x-wav");
  345     }
  346     else if( ends_with(path, ".ogg") || ends_with(path, ".oga") )
  347     {
  348         strcpy(type, "ogg");
  349         m.mime = strdup("audio/ogg");
  350     }
  351     else if( ends_with(path, ".pcm") )
  352     {
  353         strcpy(type, "pcm");
  354         m.mime = strdup("audio/L16");
  355     }
  356     else if( ends_with(path, ".dsf") )
  357     {
  358         strcpy(type, "dsf");
  359         m.mime = strdup("audio/x-dsd");
  360     }
  361     else if( ends_with(path, ".dff") )
  362     {
  363         strcpy(type, "dff");
  364         m.mime = strdup("audio/x-dsd");
  365     }
  366     else
  367     {
  368         DPRINTF(E_WARN, L_METADATA, "Unhandled file extension on %s\n", path);
  369         return 0;
  370     }
  371 
  372     if( !(*lang) )
  373     {
  374         if( !getenv("LANG") )
  375             strcpy(lang, "en_US");
  376         else
  377             strncpyt(lang, getenv("LANG"), sizeof(lang));
  378     }
  379 
  380     if( readtags((char *)path, &song, &file, lang, type) != 0 )
  381     {
  382         DPRINTF(E_WARN, L_METADATA, "Cannot extract tags from %s!\n", path);
  383         freetags(&song);
  384         free_metadata(&m, free_flags);
  385         return 0;
  386     }
  387 
  388     if( song.dlna_pn )
  389         m.dlna_pn = strdup(song.dlna_pn);
  390     if( song.year )
  391         xasprintf(&m.date, "%04d-01-01", song.year);
  392     m.duration = duration_str(song.song_length);
  393     if( song.title && *song.title )
  394     {
  395         m.title = trim(song.title);
  396         if( (esc_tag = escape_tag(m.title, 0)) )
  397         {
  398             free_flags |= FLAG_TITLE;
  399             m.title = esc_tag;
  400         }
  401     }
  402     else
  403     {
  404         free_flags |= FLAG_TITLE;
  405         m.title = strdup(name);
  406         strip_ext(m.title);
  407     }
  408     for( i = ROLE_START; i < N_ROLE; i++ )
  409     {
  410         if( song.contributor[i] && *song.contributor[i] )
  411         {
  412             m.creator = trim(song.contributor[i]);
  413             if( strlen(m.creator) > 48 )
  414             {
  415                 m.creator = strdup("Various Artists");
  416                 free_flags |= FLAG_CREATOR;
  417             }
  418             else if( (esc_tag = escape_tag(m.creator, 0)) )
  419             {
  420                 m.creator = esc_tag;
  421                 free_flags |= FLAG_CREATOR;
  422             }
  423             m.artist = m.creator;
  424             break;
  425         }
  426     }
  427     /* If there is a album artist or band associated with the album,
  428        use it for virtual containers. */
  429     if( i < ROLE_ALBUMARTIST )
  430     {
  431         for( i = ROLE_ALBUMARTIST; i <= ROLE_BAND; i++ )
  432         {
  433             if( song.contributor[i] && *song.contributor[i] )
  434                 break;
  435         }
  436         if( i <= ROLE_BAND )
  437         {
  438             m.artist = trim(song.contributor[i]);
  439             if( strlen(m.artist) > 48 )
  440             {
  441                 m.artist = strdup("Various Artists");
  442                 free_flags |= FLAG_ARTIST;
  443             }
  444             else if( (esc_tag = escape_tag(m.artist, 0)) )
  445             {
  446                 m.artist = esc_tag;
  447                 free_flags |= FLAG_ARTIST;
  448             }
  449         }
  450     }
  451     if( song.album && *song.album )
  452     {
  453         m.album = trim(song.album);
  454         if( (esc_tag = escape_tag(m.album, 0)) )
  455         {
  456             free_flags |= FLAG_ALBUM;
  457             m.album = esc_tag;
  458         }
  459     }
  460     if( song.genre && *song.genre )
  461     {
  462         m.genre = trim(song.genre);
  463         if( (esc_tag = escape_tag(m.genre, 0)) )
  464         {
  465             free_flags |= FLAG_GENRE;
  466             m.genre = esc_tag;
  467         }
  468     }
  469     if( song.comment && *song.comment )
  470     {
  471         m.comment = trim(song.comment);
  472         if( (esc_tag = escape_tag(m.comment, 0)) )
  473         {
  474             free_flags |= FLAG_COMMENT;
  475             m.comment = esc_tag;
  476         }
  477     }
  478 
  479     album_art = find_album_art(path, song.image, song.image_size);
  480 
  481     ret = sql_exec(db, "INSERT into DETAILS"
  482                        " (PATH, SIZE, TIMESTAMP, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE,"
  483                        "  TITLE, CREATOR, ARTIST, ALBUM, GENRE, COMMENT, DISC, TRACK, DLNA_PN, MIME, ALBUM_ART) "
  484                        "VALUES"
  485                        " (%Q, %lld, %lld, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, %d, %Q, '%s', %lld);",
  486                        path, (long long)file.st_size, (long long)file.st_mtime, m.duration, song.channels, song.bitrate,
  487                        song.samplerate, m.date, m.title, m.creator, m.artist, m.album, m.genre, m.comment, song.disc,
  488                        song.track, m.dlna_pn, song.mime?song.mime:m.mime, album_art);
  489     if( ret != SQLITE_OK )
  490     {
  491         DPRINTF(E_ERROR, L_METADATA, "Error inserting details for '%s'!\n", path);
  492         ret = 0;
  493     }
  494     else
  495     {
  496         ret = sqlite3_last_insert_rowid(db);
  497     }
  498     freetags(&song);
  499     free_metadata(&m, free_flags);
  500 
  501     return ret;
  502 }
  503 
  504 /* For libjpeg error handling */
  505 static jmp_buf setjmp_buffer;
  506 static void
  507 libjpeg_error_handler(j_common_ptr cinfo)
  508 {
  509     cinfo->err->output_message (cinfo);
  510     longjmp(setjmp_buffer, 1);
  511     return;
  512 }
  513 
  514 int64_t
  515 GetImageMetadata(const char *path, const char *name)
  516 {
  517     ExifData *ed;
  518     ExifEntry *e = NULL;
  519     ExifLoader *l;
  520     struct jpeg_decompress_struct cinfo;
  521     struct jpeg_error_mgr jerr;
  522     FILE *infile;
  523     int width=0, height=0, thumb=0;
  524     char make[32], model[64] = {'\0'};
  525     char b[1024];
  526     struct stat file;
  527     int64_t ret;
  528     image_s *imsrc;
  529     metadata_t m;
  530     uint32_t free_flags = 0xFFFFFFFF;
  531     memset(&m, '\0', sizeof(metadata_t));
  532 
  533     //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path);
  534     if ( stat(path, &file) != 0 )
  535         return 0;
  536     //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size);
  537 
  538     /* MIME hard-coded to JPEG for now, until we add PNG support */
  539     m.mime = strdup("image/jpeg");
  540 
  541     l = exif_loader_new();
  542     exif_loader_write_file(l, path);
  543     ed = exif_loader_get_data(l);
  544     exif_loader_unref(l);
  545     if( !ed )
  546         goto no_exifdata;
  547 
  548     e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL);
  549     if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED)) )
  550     {
  551         m.date = strdup(exif_entry_get_value(e, b, sizeof(b)));
  552         if( strlen(m.date) > 10 )
  553         {
  554             m.date[4] = '-';
  555             m.date[7] = '-';
  556             m.date[10] = 'T';
  557         }
  558         else {
  559             free(m.date);
  560             m.date = NULL;
  561         }
  562     }
  563     else {
  564         /* One last effort to get the date from XMP */
  565         image_get_jpeg_date_xmp(path, &m.date);
  566     }
  567     //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", m.date);
  568 
  569     e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
  570     if( e )
  571     {
  572         strncpyt(make, exif_entry_get_value(e, b, sizeof(b)), sizeof(make));
  573         e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL);
  574         if( e )
  575         {
  576             strncpyt(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model));
  577             if( !strcasestr(model, make) )
  578                 snprintf(model, sizeof(model), "%s %s", make, exif_entry_get_value(e, b, sizeof(b)));
  579             m.creator = escape_tag(trim(model), 1);
  580         }
  581     }
  582     //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model);
  583 
  584     e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION);
  585     if( e )
  586     {
  587         switch( exif_get_short(e->data, exif_data_get_byte_order(ed)) )
  588         {
  589         case 3:
  590             m.rotation = 180;
  591             break;
  592         case 6:
  593             m.rotation = 90;
  594             break;
  595         case 8:
  596             m.rotation = 270;
  597             break;
  598         default:
  599             m.rotation = 0;
  600             break;
  601         }
  602     }
  603 
  604     if( ed->size )
  605     {
  606         /* We might need to verify that the thumbnail is 160x160 or smaller */
  607         if( ed->size > 12000 )
  608         {
  609             imsrc = image_new_from_jpeg(NULL, 0, ed->data, ed->size, 1, ROTATE_NONE);
  610             if( imsrc )
  611             {
  612                 if( (imsrc->width <= 160) && (imsrc->height <= 160) )
  613                     thumb = 1;
  614                 image_free(imsrc);
  615             }
  616         }
  617         else
  618             thumb = 1;
  619     }
  620     //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * thumbnail: %d\n", thumb);
  621 
  622     exif_data_unref(ed);
  623 
  624 no_exifdata:
  625     /* If SOF parsing fails, then fall through to reading the JPEG data with libjpeg to get the resolution */
  626     if( image_get_jpeg_resolution(path, &width, &height) != 0 || !width || !height )
  627     {
  628         infile = fopen(path, "r");
  629         if( infile )
  630         {
  631             cinfo.err = jpeg_std_error(&jerr);
  632             jerr.error_exit = libjpeg_error_handler;
  633             jpeg_create_decompress(&cinfo);
  634             if( setjmp(setjmp_buffer) )
  635                 goto error;
  636             jpeg_stdio_src(&cinfo, infile);
  637             jpeg_read_header(&cinfo, TRUE);
  638             jpeg_start_decompress(&cinfo);
  639             width = cinfo.output_width;
  640             height = cinfo.output_height;
  641             error:
  642             jpeg_destroy_decompress(&cinfo);
  643             fclose(infile);
  644         }
  645     }
  646     //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * resolution: %dx%d\n", width, height);
  647 
  648     if( !width || !height )
  649     {
  650         free_metadata(&m, free_flags);
  651         return 0;
  652     }
  653     if( width <= 640 && height <= 480 )
  654         m.dlna_pn = strdup("JPEG_SM");
  655     else if( width <= 1024 && height <= 768 )
  656         m.dlna_pn = strdup("JPEG_MED");
  657     else if( (width <= 4096 && height <= 4096) || !GETFLAG(DLNA_STRICT_MASK) )
  658         m.dlna_pn = strdup("JPEG_LRG");
  659     xasprintf(&m.resolution, "%dx%d", width, height);
  660     m.title = strdup(name);
  661     strip_ext(m.title);
  662 
  663     ret = sql_exec(db, "INSERT into DETAILS"
  664                        " (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION,"
  665                         " ROTATION, THUMBNAIL, CREATOR, DLNA_PN, MIME) "
  666                        "VALUES"
  667                        " (%Q, '%q', %lld, %lld, %Q, %Q, %u, %d, %Q, %Q, %Q);",
  668                        path, m.title, (long long)file.st_size, (long long)file.st_mtime, m.date,
  669                        m.resolution, m.rotation, thumb, m.creator, m.dlna_pn, m.mime);
  670     if( ret != SQLITE_OK )
  671     {
  672         DPRINTF(E_ERROR, L_METADATA, "Error inserting details for '%s'!\n", path);
  673         ret = 0;
  674     }
  675     else
  676     {
  677         ret = sqlite3_last_insert_rowid(db);
  678     }
  679     free_metadata(&m, free_flags);
  680 
  681     return ret;
  682 }
  683 
  684 int64_t
  685 GetVideoMetadata(const char *path, const char *name)
  686 {
  687     struct stat file;
  688     int ret, i;
  689     struct tm *modtime;
  690     AVFormatContext *ctx = NULL;
  691     AVStream *astream = NULL, *vstream = NULL;
  692     int audio_stream = -1, video_stream = -1;
  693     enum audio_profiles audio_profile = PROFILE_AUDIO_UNKNOWN;
  694     char fourcc[4];
  695     int64_t album_art = 0;
  696     char nfo[MAXPATHLEN], *ext;
  697     struct song_metadata video;
  698     metadata_t m;
  699     uint32_t free_flags = 0xFFFFFFFF;
  700     char *path_cpy, *basepath;
  701 
  702     memset(&m, '\0', sizeof(m));
  703     memset(&video, '\0', sizeof(video));
  704 
  705     //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing video %s...\n", name);
  706     if ( stat(path, &file) != 0 )
  707         return 0;
  708     //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size);
  709 
  710     ret = lav_open(&ctx, path);
  711     if( ret != 0 )
  712     {
  713         char err[128];
  714         av_strerror(ret, err, sizeof(err));
  715         DPRINTF(E_WARN, L_METADATA, "Opening %s failed! [%s]\n", path, err);
  716         return 0;
  717     }
  718     //dump_format(ctx, 0, NULL, 0);
  719     for( i=0; i < ctx->nb_streams; i++)
  720     {
  721         if( lav_codec_type(ctx->streams[i]) == AVMEDIA_TYPE_AUDIO &&
  722             audio_stream == -1 )
  723         {
  724             audio_stream = i;
  725             astream = ctx->streams[audio_stream];
  726             continue;
  727         }
  728         else if( lav_codec_type(ctx->streams[i]) == AVMEDIA_TYPE_VIDEO &&
  729                  !lav_is_thumbnail_stream(ctx->streams[i], &m.thumb_data, &m.thumb_size) &&
  730                  video_stream == -1 )
  731         {
  732             video_stream = i;
  733             vstream = ctx->streams[video_stream];
  734             continue;
  735         }
  736     }
  737     path_cpy = strdup(path);
  738     basepath = basename(path_cpy);
  739     if( !vstream )
  740     {
  741         /* This must not be a video file. */
  742         lav_close(ctx);
  743         if( !is_audio(path) )
  744             DPRINTF(E_DEBUG, L_METADATA, "File %s does not contain a video stream.\n", basepath);
  745         free(path_cpy);
  746         return 0;
  747     }
  748 
  749     if( astream )
  750     {
  751         aac_object_type_t aac_type = AAC_INVALID;
  752         switch( lav_codec_id(astream) )
  753         {
  754             case AV_CODEC_ID_MP3:
  755                 audio_profile = PROFILE_AUDIO_MP3;
  756                 break;
  757             case AV_CODEC_ID_AAC:
  758                 if( !lav_codec_extradata(astream) )
  759                 {
  760                     DPRINTF(E_DEBUG, L_METADATA, "No AAC type\n");
  761                 }
  762                 else
  763                 {
  764                     uint8_t data;
  765                     memcpy(&data, lav_codec_extradata(astream), 1);
  766                     aac_type = data >> 3;
  767                 }
  768                 switch( aac_type )
  769                 {
  770                     /* AAC Low Complexity variants */
  771                     case AAC_LC:
  772                     case AAC_LC_ER:
  773                         if( lav_sample_rate(astream) < 8000 ||
  774                             lav_sample_rate(astream) > 48000 )
  775                         {
  776                             DPRINTF(E_DEBUG, L_METADATA, "Unsupported AAC: sample rate is not 8000 < %d < 48000\n",
  777                                 lav_sample_rate(astream));
  778                             break;
  779                         }
  780                         /* AAC @ Level 1/2 */
  781                         if( lav_channels(astream) <= 2 &&
  782                             lav_bit_rate(astream) <= 576000 )
  783                             audio_profile = PROFILE_AUDIO_AAC;
  784                         else if( lav_channels(astream) <= 6 &&
  785                              lav_bit_rate(astream) <= 1440000 )
  786                             audio_profile = PROFILE_AUDIO_AAC_MULT5;
  787                         else
  788                             DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC: %lld channels, %lld bitrate\n",
  789                                 (long long)lav_channels(astream),
  790                                 (long long)lav_bit_rate(astream));
  791                         break;
  792                     default:
  793                         DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC type [%d]\n", aac_type);
  794                         break;
  795                 }
  796                 break;
  797             case AV_CODEC_ID_AC3:
  798             case AV_CODEC_ID_DTS:
  799                 audio_profile = PROFILE_AUDIO_AC3;
  800                 break;
  801             case AV_CODEC_ID_WMAV1:
  802             case AV_CODEC_ID_WMAV2:
  803                 /* WMA Baseline: stereo, up to 48 KHz, up to 192,999 bps */
  804                 if ( lav_bit_rate(astream) <= 193000 )
  805                     audio_profile = PROFILE_AUDIO_WMA_BASE;
  806                 /* WMA Full: stereo, up to 48 KHz, up to 385 Kbps */
  807                 else if ( lav_bit_rate(astream) <= 385000 )
  808                     audio_profile = PROFILE_AUDIO_WMA_FULL;
  809                 break;
  810             case AV_CODEC_ID_WMAPRO:
  811                 audio_profile = PROFILE_AUDIO_WMA_PRO;
  812                 break;
  813             case AV_CODEC_ID_MP2:
  814                 audio_profile = PROFILE_AUDIO_MP2;
  815                 break;
  816             case AV_CODEC_ID_AMR_NB:
  817                 audio_profile = PROFILE_AUDIO_AMR;
  818                 break;
  819             default:
  820                 if( (lav_codec_id(astream) >= AV_CODEC_ID_PCM_S16LE) &&
  821                     (lav_codec_id(astream) < AV_CODEC_ID_ADPCM_IMA_QT) )
  822                     audio_profile = PROFILE_AUDIO_PCM;
  823                 else
  824                     DPRINTF(E_DEBUG, L_METADATA, "Unhandled audio codec [0x%X]\n", lav_codec_id(astream));
  825                 break;
  826         }
  827         m.frequency = lav_sample_rate(astream);
  828         m.channels = lav_channels(astream);
  829     }
  830     if( vstream )
  831     {
  832         int off;
  833         ts_timestamp_t ts_timestamp = NONE;
  834         DPRINTF(E_DEBUG, L_METADATA, "Container: '%s' [%s]\n", ctx->iformat->name, basepath);
  835         xasprintf(&m.resolution, "%dx%d", lav_width(vstream), lav_height(vstream));
  836         if( ctx->bit_rate > 8 )
  837             m.bitrate = ctx->bit_rate / 8;
  838         if( ctx->duration > 0 )
  839             m.duration = duration_str(ctx->duration / (AV_TIME_BASE/1000));
  840 
  841         /* NOTE: The DLNA spec only provides for ASF (WMV), TS, PS, and MP4 containers.
  842          * Skip DLNA parsing for everything else. */
  843         if( strcmp(ctx->iformat->name, "avi") == 0 )
  844         {
  845             xasprintf(&m.mime, "video/x-msvideo");
  846             if( lav_codec_id(vstream) == AV_CODEC_ID_MPEG4 )
  847             {
  848                 fourcc[0] = lav_codec_tag(vstream)     & 0xff;
  849                 fourcc[1] = lav_codec_tag(vstream)>>8  & 0xff;
  850                 fourcc[2] = lav_codec_tag(vstream)>>16 & 0xff;
  851                 fourcc[3] = lav_codec_tag(vstream)>>24 & 0xff;
  852                 if( memcmp(fourcc, "XVID", 4) == 0 ||
  853                     memcmp(fourcc, "DX50", 4) == 0 ||
  854                     memcmp(fourcc, "DIVX", 4) == 0 )
  855                     xasprintf(&m.creator, "DiVX");
  856             }
  857         }
  858         else if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 &&
  859                  ends_with(path, ".mov") )
  860             xasprintf(&m.mime, "video/quicktime");
  861         else if( strncmp(ctx->iformat->name, "matroska", 8) == 0 )
  862             xasprintf(&m.mime, "video/x-matroska");
  863         else if( strcmp(ctx->iformat->name, "flv") == 0 )
  864             xasprintf(&m.mime, "video/x-flv");
  865         if( m.mime )
  866             goto video_no_dlna;
  867 
  868         switch( lav_codec_id(vstream) )
  869         {
  870             case AV_CODEC_ID_MPEG1VIDEO:
  871                 if( strcmp(ctx->iformat->name, "mpeg") == 0 )
  872                 {
  873                     if( (lav_width(vstream)  == 352) &&
  874                         (lav_height(vstream) <= 288) )
  875                     {
  876                         m.dlna_pn = strdup("MPEG1");
  877                     }
  878                     xasprintf(&m.mime, "video/mpeg");
  879                 }
  880                 break;
  881             case AV_CODEC_ID_MPEG2VIDEO:
  882                 m.dlna_pn = malloc(64);
  883                 off = sprintf(m.dlna_pn, "MPEG_");
  884                 if( strcmp(ctx->iformat->name, "mpegts") == 0 )
  885                 {
  886                     int raw_packet_size;
  887                     int dlna_ts_present = dlna_timestamp_is_present(path, &raw_packet_size);
  888                     DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s MPEG2 TS packet size %d\n",
  889                         video_stream, basepath, m.resolution, raw_packet_size);
  890                     off += sprintf(m.dlna_pn+off, "TS_");
  891                     if( (lav_width(vstream)  >= 1280) &&
  892                         (lav_height(vstream) >= 720) )
  893                     {
  894                         off += sprintf(m.dlna_pn+off, "HD_NA");
  895                     }
  896                     else
  897                     {
  898                         off += sprintf(m.dlna_pn+off, "SD_");
  899                         if( (lav_height(vstream) == 576) ||
  900                             (lav_height(vstream) == 288) )
  901                             off += sprintf(m.dlna_pn+off, "EU");
  902                         else
  903                             off += sprintf(m.dlna_pn+off, "NA");
  904                     }
  905                     if( raw_packet_size == MPEG_TS_PACKET_LENGTH_DLNA )
  906                     {
  907                         if (dlna_ts_present)
  908                             ts_timestamp = VALID;
  909                         else
  910                             ts_timestamp = EMPTY;
  911                     }
  912                     else if( raw_packet_size != MPEG_TS_PACKET_LENGTH )
  913                     {
  914                         DPRINTF(E_DEBUG, L_METADATA, "Unsupported DLNA TS packet size [%d] (%s)\n",
  915                             raw_packet_size, basepath);
  916                         free(m.dlna_pn);
  917                         m.dlna_pn = NULL;
  918                     }
  919                     switch( ts_timestamp )
  920                     {
  921                         case NONE:
  922                             xasprintf(&m.mime, "video/mpeg");
  923                             if( m.dlna_pn )
  924                                 off += sprintf(m.dlna_pn+off, "_ISO");
  925                             break;
  926                         case VALID:
  927                             off += sprintf(m.dlna_pn+off, "_T");
  928                         case EMPTY:
  929                             xasprintf(&m.mime, "video/vnd.dlna.mpeg-tts");
  930                         default:
  931                             break;
  932                     }
  933                 }
  934                 else if( strcmp(ctx->iformat->name, "mpeg") == 0 )
  935                 {
  936                     DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s MPEG2 PS\n",
  937                         video_stream, basepath, m.resolution);
  938                     off += sprintf(m.dlna_pn+off, "PS_");
  939                     if( (lav_height(vstream) == 576) ||
  940                         (lav_height(vstream) == 288) )
  941                         off += sprintf(m.dlna_pn+off, "PAL");
  942                     else
  943                         off += sprintf(m.dlna_pn+off, "NTSC");
  944                     xasprintf(&m.mime, "video/mpeg");
  945                 }
  946                 else
  947                 {
  948                     DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s [%s] is %s non-DLNA MPEG2\n",
  949                         video_stream, basepath, ctx->iformat->name, m.resolution);
  950                     free(m.dlna_pn);
  951                     m.dlna_pn = NULL;
  952                 }
  953                 break;
  954             case AV_CODEC_ID_H264:
  955                 m.dlna_pn = malloc(128);
  956                 off = sprintf(m.dlna_pn, "AVC_");
  957 
  958                 if( strcmp(ctx->iformat->name, "mpegts") == 0 )
  959                 {
  960                     AVRational display_aspect_ratio;
  961                     int fps, interlaced;
  962                     int raw_packet_size;
  963                     int dlna_ts_present = dlna_timestamp_is_present(path, &raw_packet_size);
  964 
  965                     off += sprintf(m.dlna_pn+off, "TS_");
  966                     if (lav_sample_aspect_ratio(vstream).num) {
  967                         av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
  968                                   lav_width(vstream) * lav_sample_aspect_ratio(vstream).num,
  969                                   lav_height(vstream) * lav_sample_aspect_ratio(vstream).den,
  970                                   1024*1024);
  971                     }
  972                     fps = lav_get_fps(vstream);
  973                     interlaced = lav_get_interlaced(vstream);
  974                     if( ((((lav_width(vstream) == 1920 || lav_width(vstream) == 1440) && lav_height(vstream) == 1080) ||
  975                           (lav_width(vstream) == 720 && lav_height(vstream) == 480)) && fps == 59 && interlaced) ||
  976                         ((lav_width(vstream) == 1280 && lav_height(vstream) == 720) && fps == 59 && !interlaced) )
  977                     {
  978                         if( (lav_profile(vstream) == FF_PROFILE_H264_MAIN || lav_profile(vstream) == FF_PROFILE_H264_HIGH) &&
  979                             audio_profile == PROFILE_AUDIO_AC3 )
  980                         {
  981                             off += sprintf(m.dlna_pn+off, "HD_60_");
  982                             lav_profile(vstream) = FF_PROFILE_SKIP;
  983                         }
  984                     }
  985                     else if( ((lav_width(vstream) == 1920 && lav_height(vstream) == 1080) ||
  986                               (lav_width(vstream) == 1440 && lav_height(vstream) == 1080) ||
  987                               (lav_width(vstream) == 1280 && lav_height(vstream) ==  720) ||
  988                               (lav_width(vstream) ==  720 && lav_height(vstream) ==  576)) &&
  989                               interlaced && fps == 50 )
  990                     {
  991                         if( (lav_profile(vstream) == FF_PROFILE_H264_MAIN || lav_profile(vstream) == FF_PROFILE_H264_HIGH) &&
  992                             audio_profile == PROFILE_AUDIO_AC3 )
  993                         {
  994                             off += sprintf(m.dlna_pn+off, "HD_50_");
  995                             lav_profile(vstream) = FF_PROFILE_SKIP;
  996                         }
  997                     }
  998                     switch( lav_profile(vstream) )
  999                     {
 1000                         case FF_PROFILE_H264_BASELINE:
 1001                         case FF_PROFILE_H264_CONSTRAINED_BASELINE:
 1002                             off += sprintf(m.dlna_pn+off, "BL_");
 1003                             if( lav_width(vstream)  <= 352 &&
 1004                                 lav_height(vstream) <= 288 &&
 1005                                 lav_bit_rate(vstream) <= 384000 )
 1006                             {
 1007                                 off += sprintf(m.dlna_pn+off, "CIF15_");
 1008                                 break;
 1009                             }
 1010                             else if( lav_width(vstream)  <= 352 &&
 1011                                      lav_height(vstream) <= 288 &&
 1012                                      lav_bit_rate(vstream) <= 3000000 )
 1013                             {
 1014                                 off += sprintf(m.dlna_pn+off, "CIF30_");
 1015                                 break;
 1016                             }
 1017                             /* Fall back to Main Profile if it doesn't match a Baseline DLNA profile. */
 1018                             else
 1019                                 off -= 3;
 1020                         default:
 1021                         case FF_PROFILE_H264_MAIN:
 1022                             off += sprintf(m.dlna_pn+off, "MP_");
 1023                             if( lav_profile(vstream) != FF_PROFILE_H264_BASELINE &&
 1024                                 lav_profile(vstream) != FF_PROFILE_H264_CONSTRAINED_BASELINE &&
 1025                                 lav_profile(vstream) != FF_PROFILE_H264_MAIN )
 1026                             {
 1027                                 DPRINTF(E_DEBUG, L_METADATA, "Unknown AVC profile %d; assuming MP. [%s]\n",
 1028                                     lav_profile(vstream), basepath);
 1029                             }
 1030                             if( lav_width(vstream)  <= 720 &&
 1031                                 lav_height(vstream) <= 576 &&
 1032                                 lav_bit_rate(vstream) <= 10000000 )
 1033                             {
 1034                                 off += sprintf(m.dlna_pn+off, "SD_");
 1035                             }
 1036                             else if( lav_width(vstream)  <= 1920 &&
 1037                                      lav_height(vstream) <= 1152 &&
 1038                                      lav_bit_rate(vstream) <= 20000000 )
 1039                             {
 1040                                 off += sprintf(m.dlna_pn+off, "HD_");
 1041                             }
 1042                             else
 1043                             {
 1044                                 DPRINTF(E_DEBUG, L_METADATA, "Unsupported h.264 video profile! [%s, %dx%d, %lldbps : %s]\n",
 1045                                     m.dlna_pn, lav_width(vstream), lav_height(vstream),
 1046                                     (long long)lav_bit_rate(vstream), basepath);
 1047                                 free(m.dlna_pn);
 1048                                 m.dlna_pn = NULL;
 1049                             }
 1050                             break;
 1051                         case FF_PROFILE_H264_HIGH:
 1052                             off += sprintf(m.dlna_pn+off, "HP_");
 1053                             if( lav_width(vstream)  <= 1920 &&
 1054                                 lav_height(vstream) <= 1152 &&
 1055                                 lav_bit_rate(vstream) <= 30000000 &&
 1056                                 audio_profile == PROFILE_AUDIO_AC3 )
 1057                             {
 1058                                 off += sprintf(m.dlna_pn+off, "HD_");
 1059                             }
 1060                             else
 1061                             {
 1062                                 DPRINTF(E_DEBUG, L_METADATA, "Unsupported h.264 HP video profile! [%lldbps, %d audio : %s]\n",
 1063                                     (long long)lav_bit_rate(vstream), audio_profile, basepath);
 1064                                 free(m.dlna_pn);
 1065                                 m.dlna_pn = NULL;
 1066                             }
 1067                             break;
 1068                         case FF_PROFILE_SKIP:
 1069                             break;
 1070                     }
 1071                     if( !m.dlna_pn )
 1072                         break;
 1073                     switch( audio_profile )
 1074                     {
 1075                         case PROFILE_AUDIO_MP3:
 1076                             off += sprintf(m.dlna_pn+off, "MPEG1_L3");
 1077                             break;
 1078                         case PROFILE_AUDIO_AC3:
 1079                             off += sprintf(m.dlna_pn+off, "AC3");
 1080                             break;
 1081                         case PROFILE_AUDIO_AAC:
 1082                         case PROFILE_AUDIO_AAC_MULT5:
 1083                             off += sprintf(m.dlna_pn+off, "AAC_MULT5");
 1084                             break;
 1085                         default:
 1086                             DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for %s file [%s]\n",
 1087                                 m.dlna_pn, basepath);
 1088                             free(m.dlna_pn);
 1089                             m.dlna_pn = NULL;
 1090                             break;
 1091                     }
 1092                     if( !m.dlna_pn )
 1093                         break;
 1094                     if( raw_packet_size == MPEG_TS_PACKET_LENGTH_DLNA )
 1095                     {
 1096                         if( lav_profile(vstream) == FF_PROFILE_H264_HIGH ||
 1097                             dlna_ts_present )
 1098                             ts_timestamp = VALID;
 1099                         else
 1100                             ts_timestamp = EMPTY;
 1101                     }
 1102                     else if( raw_packet_size != MPEG_TS_PACKET_LENGTH )
 1103                     {
 1104                         DPRINTF(E_DEBUG, L_METADATA, "Unsupported DLNA TS packet size [%d] (%s)\n",
 1105                             raw_packet_size, basepath);
 1106                         free(m.dlna_pn);
 1107                         m.dlna_pn = NULL;
 1108                     }
 1109                     switch( ts_timestamp )
 1110                     {
 1111                         case NONE:
 1112                             if( m.dlna_pn )
 1113                                 off += sprintf(m.dlna_pn+off, "_ISO");
 1114                             break;
 1115                         case VALID:
 1116                             off += sprintf(m.dlna_pn+off, "_T");
 1117                         case EMPTY:
 1118                             xasprintf(&m.mime, "video/vnd.dlna.mpeg-tts");
 1119                         default:
 1120                             break;
 1121                     }
 1122                 }
 1123                 else if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
 1124                 {
 1125                     off += sprintf(m.dlna_pn+off, "MP4_");
 1126 
 1127                     switch( lav_profile(vstream) ) {
 1128                     case FF_PROFILE_H264_BASELINE:
 1129                     case FF_PROFILE_H264_CONSTRAINED_BASELINE:
 1130                         if( lav_width(vstream)  <= 352 &&
 1131                             lav_height(vstream) <= 288 )
 1132                         {
 1133                             if( ctx->bit_rate < 600000 )
 1134                                 off += sprintf(m.dlna_pn+off, "BL_CIF15_");
 1135                             else if( ctx->bit_rate < 5000000 )
 1136                                 off += sprintf(m.dlna_pn+off, "BL_CIF30_");
 1137                             else
 1138                                 goto mp4_mp_fallback;
 1139 
 1140                             if( audio_profile == PROFILE_AUDIO_AMR )
 1141                             {
 1142                                 off += sprintf(m.dlna_pn+off, "AMR");
 1143                             }
 1144                             else if( audio_profile == PROFILE_AUDIO_AAC )
 1145                             {
 1146                                 off += sprintf(m.dlna_pn+off, "AAC_");
 1147                                 if( ctx->bit_rate < 520000 )
 1148                                 {
 1149                                     off += sprintf(m.dlna_pn+off, "520");
 1150                                 }
 1151                                 else if( ctx->bit_rate < 940000 )
 1152                                 {
 1153                                     off += sprintf(m.dlna_pn+off, "940");
 1154                                 }
 1155                                 else
 1156                                 {
 1157                                     off -= 13;
 1158                                     goto mp4_mp_fallback;
 1159                                 }
 1160                             }
 1161                             else
 1162                             {
 1163                                 off -= 9;
 1164                                 goto mp4_mp_fallback;
 1165                             }
 1166                         }
 1167                         else if( lav_width(vstream)  <= 720 &&
 1168                                  lav_height(vstream) <= 576 )
 1169                         {
 1170                             if( lav_level(vstream) == 30 &&
 1171                                 audio_profile == PROFILE_AUDIO_AAC &&
 1172                                 ctx->bit_rate <= 5000000 )
 1173                                 off += sprintf(m.dlna_pn+off, "BL_L3L_SD_AAC");
 1174                             else if( lav_level(vstream) <= 31 &&
 1175                                      audio_profile == PROFILE_AUDIO_AAC &&
 1176                                      ctx->bit_rate <= 15000000 )
 1177                                 off += sprintf(m.dlna_pn+off, "BL_L31_HD_AAC");
 1178                             else
 1179                                 goto mp4_mp_fallback;
 1180                         }
 1181                         else if( lav_width(vstream)  <= 1280 &&
 1182                                  lav_height(vstream) <= 720 )
 1183                         {
 1184                             if( lav_level(vstream) <= 31 &&
 1185                                 audio_profile == PROFILE_AUDIO_AAC &&
 1186                                 ctx->bit_rate <= 15000000 )
 1187                                 off += sprintf(m.dlna_pn+off, "BL_L31_HD_AAC");
 1188                             else if( lav_level(vstream) <= 32 &&
 1189                                      audio_profile == PROFILE_AUDIO_AAC &&
 1190                                      ctx->bit_rate <= 21000000 )
 1191                                 off += sprintf(m.dlna_pn+off, "BL_L32_HD_AAC");
 1192                             else
 1193                                 goto mp4_mp_fallback;
 1194                         }
 1195                         else
 1196                             goto mp4_mp_fallback;
 1197                         break;
 1198                     case FF_PROFILE_H264_MAIN:
 1199                     mp4_mp_fallback:
 1200                         off += sprintf(m.dlna_pn+off, "MP_");
 1201                         /* AVC MP4 SD profiles - 10 Mbps max */
 1202                         if( lav_width(vstream)  <= 720 &&
 1203                             lav_height(vstream) <= 576 &&
 1204                             lav_bit_rate(vstream) <= 10000000 )
 1205                         {
 1206                             sprintf(m.dlna_pn+off, "SD_");
 1207                             if( audio_profile == PROFILE_AUDIO_AC3 )
 1208                                 off += sprintf(m.dlna_pn+off, "AC3");
 1209                             else if( audio_profile == PROFILE_AUDIO_AAC ||
 1210                                      audio_profile == PROFILE_AUDIO_AAC_MULT5 )
 1211                                 off += sprintf(m.dlna_pn+off, "AAC_MULT5");
 1212                             else if( audio_profile == PROFILE_AUDIO_MP3 )
 1213                                 off += sprintf(m.dlna_pn+off, "MPEG1_L3");
 1214                             else
 1215                                 m.dlna_pn[10] = '\0';
 1216                         }
 1217                         else if( lav_width(vstream)  <= 1280 &&
 1218                                  lav_height(vstream) <= 720 &&
 1219                                  lav_bit_rate(vstream) <= 15000000 &&
 1220                                  audio_profile == PROFILE_AUDIO_AAC )
 1221                         {
 1222                             off += sprintf(m.dlna_pn+off, "HD_720p_AAC");
 1223                         }
 1224                         else if( lav_width(vstream)  <= 1920 &&
 1225                                  lav_height(vstream) <= 1080 &&
 1226                                  lav_bit_rate(vstream) <= 21000000 &&
 1227                                  audio_profile == PROFILE_AUDIO_AAC )
 1228                         {
 1229                             off += sprintf(m.dlna_pn+off, "HD_1080i_AAC");
 1230                         }
 1231                         if( strlen(m.dlna_pn) <= 11 )
 1232                         {
 1233                             DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for %s file %s\n",
 1234                                 m.dlna_pn, basepath);
 1235                             free(m.dlna_pn);
 1236                             m.dlna_pn = NULL;
 1237                         }
 1238                         break;
 1239                     case FF_PROFILE_H264_HIGH:
 1240                         if( lav_width(vstream)  <= 1920 &&
 1241                             lav_height(vstream) <= 1080 &&
 1242                             lav_bit_rate(vstream) <= 25000000 &&
 1243                             audio_profile == PROFILE_AUDIO_AAC )
 1244                         {
 1245                             off += sprintf(m.dlna_pn+off, "HP_HD_AAC");
 1246                         }
 1247                         break;
 1248                     default:
 1249                         DPRINTF(E_DEBUG, L_METADATA, "AVC profile [%d] not recognized for file %s\n",
 1250                             lav_profile(vstream), basepath);
 1251                         free(m.dlna_pn);
 1252                         m.dlna_pn = NULL;
 1253                         break;
 1254                     }
 1255                 }
 1256                 else
 1257                 {
 1258                     free(m.dlna_pn);
 1259                     m.dlna_pn = NULL;
 1260                 }
 1261                 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is h.264\n", video_stream, basepath);
 1262                 break;
 1263             case AV_CODEC_ID_MPEG4:
 1264                 fourcc[0] = lav_codec_tag(vstream)     & 0xff;
 1265                 fourcc[1] = lav_codec_tag(vstream)>>8  & 0xff;
 1266                 fourcc[2] = lav_codec_tag(vstream)>>16 & 0xff;
 1267                 fourcc[3] = lav_codec_tag(vstream)>>24 & 0xff;
 1268                 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is MPEG4 [%c%c%c%c/0x%X]\n",
 1269                     video_stream, basepath,
 1270                     isprint(fourcc[0]) ? fourcc[0] : '_',
 1271                     isprint(fourcc[1]) ? fourcc[1] : '_',
 1272                     isprint(fourcc[2]) ? fourcc[2] : '_',
 1273                     isprint(fourcc[3]) ? fourcc[3] : '_',
 1274                     lav_codec_tag(vstream));
 1275 
 1276                 if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
 1277                 {
 1278                     m.dlna_pn = malloc(128);
 1279                     off = sprintf(m.dlna_pn, "MPEG4_P2_");
 1280 
 1281                     if( ends_with(path, ".3gp") )
 1282                     {
 1283                         xasprintf(&m.mime, "video/3gpp");
 1284                         switch( audio_profile )
 1285                         {
 1286                             case PROFILE_AUDIO_AAC:
 1287                                 off += sprintf(m.dlna_pn+off, "3GPP_SP_L0B_AAC");
 1288                                 break;
 1289                             case PROFILE_AUDIO_AMR:
 1290                                 off += sprintf(m.dlna_pn+off, "3GPP_SP_L0B_AMR");
 1291                                 break;
 1292                             default:
 1293                                 DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for MPEG4-P2 3GP/%d file %s\n",
 1294                                         audio_profile, basepath);
 1295                                 free(m.dlna_pn);
 1296                                 m.dlna_pn = NULL;
 1297                                 break;
 1298                         }
 1299                     }
 1300                     else
 1301                     {
 1302                         if( ctx->bit_rate <= 1000000 &&
 1303                             audio_profile == PROFILE_AUDIO_AAC )
 1304                         {
 1305                             off += sprintf(m.dlna_pn+off, "MP4_ASP_AAC");
 1306                         }
 1307                         else if( ctx->bit_rate <= 4000000 &&
 1308                                  lav_width(vstream)  <= 640 &&
 1309                                  lav_height(vstream) <= 480 &&
 1310                                  audio_profile == PROFILE_AUDIO_AAC )
 1311                         {
 1312                             off += sprintf(m.dlna_pn+off, "MP4_SP_VGA_AAC");
 1313                         }
 1314                         else
 1315                         {
 1316                             DPRINTF(E_DEBUG, L_METADATA, "Unsupported h.264 video profile! [%dx%d, %lldbps]\n",
 1317                                 lav_width(vstream),
 1318                                 lav_height(vstream),
 1319                                 (long long)ctx->bit_rate);
 1320                             free(m.dlna_pn);
 1321                             m.dlna_pn = NULL;
 1322                         }
 1323                     }
 1324                 }
 1325                 break;
 1326             case AV_CODEC_ID_WMV3:
 1327                 /* I'm not 100% sure this is correct, but it works on everything I could get my hands on */
 1328                 if( lav_codec_extradata(vstream) )
 1329                 {
 1330                     if( !((lav_codec_extradata(vstream)[0] >> 3) & 1) )
 1331                         lav_level(vstream) = 0;
 1332                     if( !((lav_codec_extradata(vstream)[0] >> 6) & 1) )
 1333                         lav_profile(vstream) = 0;
 1334                 }
 1335             case AV_CODEC_ID_VC1:
 1336                 if( strcmp(ctx->iformat->name, "asf") != 0 )
 1337                 {
 1338                     DPRINTF(E_DEBUG, L_METADATA, "Skipping DLNA parsing for non-ASF VC1 file %s\n", path);
 1339                     break;
 1340                 }
 1341                 m.dlna_pn = malloc(64);
 1342                 off = sprintf(m.dlna_pn, "WMV");
 1343                 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is VC1\n", video_stream, basepath);
 1344                 xasprintf(&m.mime, "video/x-ms-wmv");
 1345                 if( (lav_width(vstream)  <= 176) &&
 1346                     (lav_height(vstream) <= 144) &&
 1347                     (lav_level(vstream) == 0) )
 1348                 {
 1349                     off += sprintf(m.dlna_pn+off, "SPLL_");
 1350                     switch( audio_profile )
 1351                     {
 1352                         case PROFILE_AUDIO_MP3:
 1353                             off += sprintf(m.dlna_pn+off, "MP3");
 1354                             break;
 1355                         case PROFILE_AUDIO_WMA_BASE:
 1356                             off += sprintf(m.dlna_pn+off, "BASE");
 1357                             break;
 1358                         default:
 1359                             DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for WMVSPLL/0x%X file %s\n",
 1360                                 audio_profile, basepath);
 1361                             free(m.dlna_pn);
 1362                             m.dlna_pn = NULL;
 1363                             break;
 1364                     }
 1365                 }
 1366                 else if( (lav_width(vstream)  <= 352) &&
 1367                          (lav_height(vstream) <= 288) &&
 1368                          (lav_profile(vstream) == 0) &&
 1369                          (ctx->bit_rate/8 <= 384000) )
 1370                 {
 1371                     off += sprintf(m.dlna_pn+off, "SPML_");
 1372                     switch( audio_profile )
 1373                     {
 1374                         case PROFILE_AUDIO_MP3:
 1375                             off += sprintf(m.dlna_pn+off, "MP3");
 1376                             break;
 1377                         case PROFILE_AUDIO_WMA_BASE:
 1378                             off += sprintf(m.dlna_pn+off, "BASE");
 1379                             break;
 1380                         default:
 1381                             DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for WMVSPML/0x%X file %s\n",
 1382                                 audio_profile, basepath);
 1383                             free(m.dlna_pn);
 1384                             m.dlna_pn = NULL;
 1385                             break;
 1386                     }
 1387                 }
 1388                 else if( (lav_width(vstream)  <= 720) &&
 1389                          (lav_height(vstream) <= 576) &&
 1390                          (ctx->bit_rate/8 <= 10000000) )
 1391                 {
 1392                     off += sprintf(m.dlna_pn+off, "MED_");
 1393                     switch( audio_profile )
 1394                     {
 1395                         case PROFILE_AUDIO_WMA_PRO:
 1396                             off += sprintf(m.dlna_pn+off, "PRO");
 1397                             break;
 1398                         case PROFILE_AUDIO_WMA_FULL:
 1399                             off += sprintf(m.dlna_pn+off, "FULL");
 1400                             break;
 1401                         case PROFILE_AUDIO_WMA_BASE:
 1402                             off += sprintf(m.dlna_pn+off, "BASE");
 1403                             break;
 1404                         default:
 1405                             DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for WMVMED/0x%X file %s\n",
 1406                                 audio_profile, basepath);
 1407                             free(m.dlna_pn);
 1408                             m.dlna_pn = NULL;
 1409                             break;
 1410                     }
 1411                 }
 1412                 else if( (lav_width(vstream)  <= 1920) &&
 1413                          (lav_height(vstream) <= 1080) &&
 1414                          (ctx->bit_rate/8 <= 20000000) )
 1415                 {
 1416                     off += sprintf(m.dlna_pn+off, "HIGH_");
 1417                     switch( audio_profile )
 1418                     {
 1419                         case PROFILE_AUDIO_WMA_PRO:
 1420                             off += sprintf(m.dlna_pn+off, "PRO");
 1421                             break;
 1422                         case PROFILE_AUDIO_WMA_FULL:
 1423                             off += sprintf(m.dlna_pn+off, "FULL");
 1424                             break;
 1425                         default:
 1426                             DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for WMVHIGH/0x%X file %s\n",
 1427                                 audio_profile, basepath);
 1428                             free(m.dlna_pn);
 1429                             m.dlna_pn = NULL;
 1430                             break;
 1431                     }
 1432                 }
 1433                 break;
 1434             case AV_CODEC_ID_MSMPEG4V3:
 1435                 xasprintf(&m.mime, "video/x-msvideo");
 1436             default:
 1437                 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s [type %d]\n",
 1438                     video_stream, basepath, m.resolution, lav_codec_id(vstream));
 1439                 break;
 1440         }
 1441     }
 1442 
 1443     if( strcmp(ctx->iformat->name, "asf") == 0 )
 1444     {
 1445         if( readtags((char *)path, &video, &file, "en_US", "asf") == 0 )
 1446         {
 1447             if( video.title && *video.title )
 1448             {
 1449                 m.title = escape_tag(trim(video.title), 1);
 1450             }
 1451             if( video.genre && *video.genre )
 1452             {
 1453                 m.genre = escape_tag(trim(video.genre), 1);
 1454             }
 1455             if( video.contributor[ROLE_TRACKARTIST] && *video.contributor[ROLE_TRACKARTIST] )
 1456             {
 1457                 m.artist = escape_tag(trim(video.contributor[ROLE_TRACKARTIST]), 1);
 1458             }
 1459             if( video.contributor[ROLE_ALBUMARTIST] && *video.contributor[ROLE_ALBUMARTIST] )
 1460             {
 1461                 m.creator = escape_tag(trim(video.contributor[ROLE_ALBUMARTIST]), 1);
 1462             }
 1463             else
 1464             {
 1465                 m.creator = m.artist;
 1466                 free_flags &= ~FLAG_CREATOR;
 1467             }
 1468             if (!m.thumb_data)
 1469             {
 1470                 m.thumb_data = video.image;
 1471                 m.thumb_size = video.image_size;
 1472             }
 1473         }
 1474     }
 1475     #ifndef NETGEAR
 1476     #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
 1477     else if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
 1478     {
 1479         if( ctx->metadata )
 1480         {
 1481             AVDictionaryEntry *tag = NULL;
 1482 
 1483             //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Metadata:\n");
 1484             while( (tag = av_dict_get(ctx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)) )
 1485             {
 1486                 //DEBUG DPRINTF(E_DEBUG, L_METADATA, "  %-16s: %s\n", tag->key, tag->value);
 1487                 if( strcmp(tag->key, "title") == 0 )
 1488                     m.title = escape_tag(trim(tag->value), 1);
 1489                 else if( strcmp(tag->key, "genre") == 0 )
 1490                     m.genre = escape_tag(trim(tag->value), 1);
 1491                 else if( strcmp(tag->key, "artist") == 0 )
 1492                     m.artist = escape_tag(trim(tag->value), 1);
 1493                 else if( strcmp(tag->key, "comment") == 0 )
 1494                     m.comment = escape_tag(trim(tag->value), 1);
 1495             }
 1496         }
 1497     }
 1498     #endif
 1499     #endif
 1500 video_no_dlna:
 1501 
 1502 #ifdef TIVO_SUPPORT
 1503     if( ends_with(path, ".TiVo") && is_tivo_file(path) )
 1504     {
 1505         if( m.dlna_pn )
 1506         {
 1507             free(m.dlna_pn);
 1508             m.dlna_pn = NULL;
 1509         }
 1510         m.mime = realloc(m.mime, 21);
 1511         strcpy(m.mime, "video/x-tivo-mpeg");
 1512     }
 1513 #endif
 1514 
 1515     strcpy(nfo, path);
 1516     ext = strrchr(nfo, '.');
 1517     if( ext )
 1518     {
 1519         strcpy(ext+1, "nfo");
 1520         if( access(nfo, R_OK) == 0 )
 1521             parse_nfo(nfo, &m);
 1522     }
 1523 
 1524     if( !m.mime )
 1525     {
 1526         if( strcmp(ctx->iformat->name, "avi") == 0 )
 1527             xasprintf(&m.mime, "video/x-msvideo");
 1528         else if( strncmp(ctx->iformat->name, "mpeg", 4) == 0 )
 1529             xasprintf(&m.mime, "video/mpeg");
 1530         else if( strcmp(ctx->iformat->name, "asf") == 0 )
 1531             xasprintf(&m.mime, "video/x-ms-wmv");
 1532         else if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
 1533             if( ends_with(path, ".mov") )
 1534                 xasprintf(&m.mime, "video/quicktime");
 1535             else
 1536                 xasprintf(&m.mime, "video/mp4");
 1537         else if( strncmp(ctx->iformat->name, "matroska", 8) == 0 )
 1538             xasprintf(&m.mime, "video/x-matroska");
 1539         else if( strcmp(ctx->iformat->name, "flv") == 0 )
 1540             xasprintf(&m.mime, "video/x-flv");
 1541         else
 1542             DPRINTF(E_WARN, L_METADATA, "%s: Unhandled format: %s\n", path, ctx->iformat->name);
 1543     }
 1544 
 1545     if( !m.date )
 1546     {
 1547         m.date = malloc(20);
 1548         modtime = localtime(&file.st_mtime);
 1549         strftime(m.date, 20, "%FT%T", modtime);
 1550     }
 1551 
 1552     if( !m.title )
 1553     {
 1554         m.title = strdup(name);
 1555         strip_ext(m.title);
 1556     }
 1557 
 1558     if (!m.disc && !m.track)
 1559     {
 1560         /* Search for Season and Episode in the filename */
 1561         char *p = (char*)name, *s;
 1562         while ((s = strpbrk(p, "Ss")))
 1563         {
 1564             unsigned season = strtoul(s+1, &p, 10);
 1565             unsigned episode = 0;
 1566             if (season > 0 && p)
 1567             {
 1568                 while (isblank(*p) || ispunct(*p))
 1569                     p++;
 1570                 if (*p == 'E' || *p == 'e')
 1571                     episode = strtoul(p+1, NULL, 10);
 1572             }
 1573             if (season && episode)
 1574             {
 1575                 m.disc = season;
 1576                 m.track = episode;
 1577             }
 1578             p = s + 1;
 1579         }
 1580     }
 1581 
 1582     album_art = find_album_art(path, m.thumb_data, m.thumb_size);
 1583     freetags(&video);
 1584     lav_close(ctx);
 1585 
 1586     ret = sql_exec(db, "INSERT into DETAILS"
 1587                        " (PATH, SIZE, TIMESTAMP, DURATION, DATE, CHANNELS, BITRATE, SAMPLERATE, RESOLUTION,"
 1588                        "  TITLE, CREATOR, ARTIST, GENRE, COMMENT, DLNA_PN, MIME, ALBUM_ART, DISC, TRACK) "
 1589                        "VALUES"
 1590                        " (%Q, %lld, %lld, %Q, %Q, %u, %u, %u, %Q, '%q', %Q, %Q, %Q, %Q, %Q, '%q', %lld, %u, %u);",
 1591                        path, (long long)file.st_size, (long long)file.st_mtime, m.duration,
 1592                        m.date, m.channels, m.bitrate, m.frequency, m.resolution,
 1593                        m.title, m.creator, m.artist, m.genre, m.comment, m.dlna_pn,
 1594                        m.mime, album_art, m.disc, m.track);
 1595     if( ret != SQLITE_OK )
 1596     {
 1597         DPRINTF(E_ERROR, L_METADATA, "Error inserting details for '%s'!\n", path);
 1598         ret = 0;
 1599     }
 1600     else
 1601     {
 1602         ret = sqlite3_last_insert_rowid(db);
 1603         check_for_captions(path, ret);
 1604     }
 1605     free_metadata(&m, free_flags);
 1606     free(path_cpy);
 1607 
 1608     return ret;
 1609 }