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