1/* MiniDLNA media server 2 * Copyright (C) 2008-2009 Justin Maggard 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 "metadata.h" 40#include "albumart.h" 41#include "utils.h" 42#include "sql.h" 43#include "log.h" 44 45#define FLAG_TITLE 0x00000001 46#define FLAG_ARTIST 0x00000002 47#define FLAG_ALBUM 0x00000004 48#define FLAG_GENRE 0x00000008 49#define FLAG_COMMENT 0x00000010 50#define FLAG_BAND 0x00000020 51 52/* Audio profile flags */ 53enum audio_profiles { 54 PROFILE_AUDIO_UNKNOWN, 55 PROFILE_AUDIO_MP3, 56 PROFILE_AUDIO_AC3, 57 PROFILE_AUDIO_WMA_BASE, 58 PROFILE_AUDIO_WMA_FULL, 59 PROFILE_AUDIO_WMA_PRO, 60 PROFILE_AUDIO_MP2, 61 PROFILE_AUDIO_PCM, 62 PROFILE_AUDIO_AAC, 63 PROFILE_AUDIO_AAC_MULT5, 64 PROFILE_AUDIO_AMR 65}; 66 67/* This function shamelessly copied from libdlna */ 68#define MPEG_TS_SYNC_CODE 0x47 69#define MPEG_TS_PACKET_LENGTH_DLNA 192 /* prepends 4 bytes to TS packet */ 70int 71dlna_timestamp_is_present(const char * filename) 72{ 73 unsigned char buffer[2*MPEG_TS_PACKET_LENGTH_DLNA+1]; 74 int fd, i; 75 76 /* read file header */ 77 fd = open(filename, O_RDONLY); 78 read(fd, buffer, MPEG_TS_PACKET_LENGTH_DLNA*2); 79 close(fd); 80 for( i=0; i < MPEG_TS_PACKET_LENGTH_DLNA; i++ ) 81 { 82 if( buffer[i] == MPEG_TS_SYNC_CODE ) 83 { 84 if (buffer[i + MPEG_TS_PACKET_LENGTH_DLNA] == MPEG_TS_SYNC_CODE) 85 { 86 if (buffer[i] == 0x00 && buffer [i+1] == 0x00 && 87 buffer [i+2] == 0x00 && buffer [i+3] == 0x00) 88 { 89 break; 90 } 91 else 92 { 93 return 1; 94 } 95 } 96 } 97 } 98 return 0; 99} 100 101#ifdef TIVO_SUPPORT 102int 103is_tivo_file(const char * path) 104{ 105 unsigned char buf[5]; 106 unsigned char hdr[5] = { 'T','i','V','o','\0' }; 107 int fd; 108 109 /* read file header */ 110 fd = open(path, O_RDONLY); 111 read(fd, buf, 5); 112 close(fd); 113 114 return( !memcmp(buf, hdr, 5) ); 115} 116#endif 117 118/* This function taken from libavutil (ffmpeg), because it's not included with all versions of libavutil. */ 119int 120get_fourcc(const char *s) 121{ 122 return (s[0]) + (s[1]<<8) + (s[2]<<16) + (s[3]<<24); 123} 124 125void 126check_for_captions(const char * path, sqlite_int64 detailID) 127{ 128 char * sql; 129 char * file = malloc(PATH_MAX); 130 char **result; 131 int ret, rows; 132 133 sprintf(file, "%s", path); 134 strip_ext(file); 135 136 /* If we weren't given a detail ID, look for one. */ 137 if( !detailID ) 138 { 139 sql = sqlite3_mprintf("SELECT ID from DETAILS where PATH glob '%q.*'" 140 " and MIME glob 'video/*' limit 1", file); 141 ret = sql_get_table(db, sql, &result, &rows, NULL); 142 if( ret == SQLITE_OK ) 143 { 144 if( rows ) 145 { 146 detailID = strtoll(result[1], NULL, 10); 147 //DEBUG DPRINTF(E_DEBUG, L_METADATA, "New file %s looks like a caption file.\n", path); 148 } 149 /*else 150 { 151 DPRINTF(E_DEBUG, L_METADATA, "No file found for caption %s.\n", path); 152 }*/ 153 sqlite3_free_table(result); 154 } 155 sqlite3_free(sql); 156 if( !detailID ) 157 goto no_source_video; 158 } 159 160 strcat(file, ".srt"); 161 if( access(file, R_OK) == 0 ) 162 { 163 sql_exec(db, "INSERT into CAPTIONS" 164 " (ID, PATH) " 165 "VALUES" 166 " (%lld, %Q)", detailID, file); 167 } 168no_source_video: 169 free(file); 170} 171 172sqlite_int64 173GetFolderMetadata(const char * name, const char * path, const char * artist, const char * genre, const char * album_art) 174{ 175 int ret; 176 177 ret = sql_exec(db, "INSERT into DETAILS" 178 " (TITLE, PATH, CREATOR, ARTIST, GENRE, ALBUM_ART) " 179 "VALUES" 180 " ('%q', %Q, %Q, %Q, %Q, %lld);", 181 name, path, artist, artist, genre, 182 album_art ? strtoll(album_art, NULL, 10) : 0); 183 if( ret != SQLITE_OK ) 184 ret = 0; 185 else 186 ret = sqlite3_last_insert_rowid(db); 187 188 return ret; 189} 190 191sqlite_int64 192GetAudioMetadata(const char * path, char * name) 193{ 194 char duration[16], mime[16], type[4]; 195 static char lang[6] = { '\0' }; 196 struct stat file; 197 sqlite_int64 ret; 198 char *title, *artist = NULL, *album = NULL, *band = NULL, *genre = NULL, *comment = NULL, *date = NULL; 199 char *esc_tag; 200 int i, free_flags = 0; 201 sqlite_int64 album_art = 0; 202 struct song_metadata song; 203 char *dlna_pn = NULL; 204 205 if ( stat(path, &file) != 0 ) 206 return 0; 207 strip_ext(name); 208 209 if( ends_with(path, ".mp3") ) 210 { 211 strcpy(type, "mp3"); 212 strcpy(mime, "audio/mpeg"); 213 } 214 else if( ends_with(path, ".m4a") || ends_with(path, ".mp4") || 215 ends_with(path, ".aac") || ends_with(path, ".m4p") ) 216 { 217 strcpy(type, "aac"); 218 strcpy(mime, "audio/mp4"); 219 } 220 else if( ends_with(path, ".3gp") ) 221 { 222 strcpy(type, "aac"); 223 strcpy(mime, "audio/3gpp"); 224 } 225 else if( ends_with(path, ".wma") || ends_with(path, ".asf") ) 226 { 227 strcpy(type, "asf"); 228 strcpy(mime, "audio/x-ms-wma"); 229 } 230 else if( ends_with(path, ".flac") || ends_with(path, ".fla") || ends_with(path, ".flc") ) 231 { 232 strcpy(type, "flc"); 233 strcpy(mime, "audio/x-flac"); 234 } 235 else if( ends_with(path, ".wav") ) 236 { 237 strcpy(type, "wav"); 238 strcpy(mime, "audio/x-wav"); 239 } 240 else if( ends_with(path, ".ogg") ) 241 { 242 strcpy(type, "ogg"); 243 strcpy(mime, "application/ogg"); 244 } 245 else if( ends_with(path, ".pcm") ) 246 { 247 strcpy(type, "pcm"); 248 strcpy(mime, "audio/L16"); 249 } 250 else 251 { 252 DPRINTF(E_WARN, L_GENERAL, "Unhandled file extension on %s\n", path); 253 return 0; 254 } 255 256 if( !(*lang) ) 257 { 258 if( !getenv("LANG") ) 259 strcpy(lang, "en_US"); 260 else 261 strncpy(lang, getenv("LANG"), 5); 262 lang[5] = '\0'; 263 } 264 265 if( readtags((char *)path, &song, &file, lang, type) != 0 ) 266 { 267 DPRINTF(E_WARN, L_GENERAL, "Cannot extract tags from %s!\n", path); 268 freetags(&song); 269 return 0; 270 } 271 272 if( song.dlna_pn ) 273 asprintf(&dlna_pn, "%s;DLNA.ORG_OP=01", song.dlna_pn); 274 if( song.year ) 275 asprintf(&date, "%04d-01-01", song.year); 276 sprintf(duration, "%d:%02d:%02d.%03d", 277 (song.song_length/3600000), 278 (song.song_length/60000%60), 279 (song.song_length/1000%60), 280 (song.song_length%1000)); 281 title = song.title; 282 if( title && *title ) 283 { 284 title = trim(title); 285 if( (esc_tag = escape_tag(title)) ) 286 { 287 free_flags |= FLAG_TITLE; 288 title = esc_tag; 289 } 290 } 291 else 292 { 293 title = name; 294 } 295 for( i=ROLE_START; i<N_ROLE; i++ ) 296 { 297 if( song.contributor[i] && *song.contributor[i] ) 298 { 299 artist = trim(song.contributor[i]); 300 if( strlen(artist) > 48 ) 301 { 302 free_flags |= FLAG_ARTIST; 303 artist = strdup("Various Artists"); 304 } 305 else if( (esc_tag = escape_tag(artist)) ) 306 { 307 free_flags |= FLAG_ARTIST; 308 artist = esc_tag; 309 } 310 band = artist; 311 break; 312 } 313 } 314 /* If there is a band associated with the album, use it for virtual containers. */ 315 if( (i != ROLE_BAND) && song.contributor[ROLE_BAND] && *song.contributor[ROLE_BAND] ) 316 { 317 band = trim(song.contributor[ROLE_BAND]); 318 if( strlen(band) > 48 ) 319 { 320 free_flags |= FLAG_BAND; 321 band = strdup("Various Artists"); 322 } 323 else if( (esc_tag = escape_tag(band)) ) 324 { 325 free_flags |= FLAG_BAND; 326 band = esc_tag; 327 } 328 } 329 if( song.album && *song.album ) 330 { 331 album = trim(song.album); 332 if( (esc_tag = escape_tag(album)) ) 333 { 334 free_flags |= FLAG_ALBUM; 335 album = esc_tag; 336 } 337 } 338 if( song.genre && *song.genre ) 339 { 340 genre = trim(song.genre); 341 if( (esc_tag = escape_tag(genre)) ) 342 { 343 free_flags |= FLAG_GENRE; 344 genre = esc_tag; 345 } 346 } 347 if( song.comment && *song.comment ) 348 { 349 comment = trim(song.comment); 350 if( (esc_tag = escape_tag(comment)) ) 351 { 352 free_flags |= FLAG_COMMENT; 353 comment = esc_tag; 354 } 355 } 356 357 album_art = find_album_art(path, song.image, song.image_size); 358 359 ret = sql_exec(db, "INSERT into DETAILS" 360 " (PATH, SIZE, TIMESTAMP, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE," 361 " TITLE, CREATOR, ARTIST, ALBUM, GENRE, COMMENT, DISC, TRACK, DLNA_PN, MIME, ALBUM_ART) " 362 "VALUES" 363 " (%Q, %lld, %ld, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, %d, %Q, '%s', %lld);", 364 path, file.st_size, file.st_mtime, duration, song.channels, song.bitrate, song.samplerate, date, 365 title, band, artist, album, genre, comment, song.disc, song.track, 366 dlna_pn, song.mime?song.mime:mime, album_art); 367 if( ret != SQLITE_OK ) 368 { 369 fprintf(stderr, "Error inserting details for '%s'!\n", path); 370 ret = 0; 371 } 372 else 373 { 374 ret = sqlite3_last_insert_rowid(db); 375 } 376 377 freetags(&song); 378 if( dlna_pn ) 379 free(dlna_pn); 380 if( date ) 381 free(date); 382 if( free_flags & FLAG_TITLE ) 383 free(title); 384 if( free_flags & FLAG_ARTIST ) 385 free(artist); 386 if( free_flags & FLAG_ALBUM ) 387 free(album); 388 if( free_flags & FLAG_BAND ) 389 free(band); 390 if( free_flags & FLAG_GENRE ) 391 free(genre); 392 if( free_flags & FLAG_COMMENT ) 393 free(comment); 394 395 return ret; 396} 397 398/* For libjpeg error handling */ 399jmp_buf setjmp_buffer; 400static void 401libjpeg_error_handler(j_common_ptr cinfo) 402{ 403 cinfo->err->output_message (cinfo); 404 longjmp(setjmp_buffer, 1); 405 return; 406} 407 408sqlite_int64 409GetImageMetadata(const char * path, char * name) 410{ 411 ExifData *ed; 412 ExifEntry *e = NULL; 413 ExifLoader *l; 414 struct jpeg_decompress_struct cinfo; 415 struct jpeg_error_mgr jerr; 416 FILE *infile; 417 int width=0, height=0, thumb=0; 418 char *date = NULL, *cam = NULL; 419 char make[32], model[64] = {'\0'}; 420 char b[1024]; 421 struct stat file; 422 sqlite_int64 ret; 423 image * imsrc; 424 metadata_t m; 425 memset(&m, '\0', sizeof(metadata_t)); 426 427 //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path); 428 if ( stat(path, &file) != 0 ) 429 return 0; 430 strip_ext(name); 431 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size); 432 433 /* MIME hard-coded to JPEG for now, until we add PNG support */ 434 asprintf(&m.mime, "image/jpeg"); 435 436 l = exif_loader_new(); 437 exif_loader_write_file(l, path); 438 ed = exif_loader_get_data(l); 439 exif_loader_unref(l); 440 if( !ed ) 441 goto no_exifdata; 442 443 e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL); 444 if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED)) ) { 445 date = strdup(exif_entry_get_value(e, b, sizeof(b))); 446 if( strlen(date) > 10 ) 447 { 448 date[4] = '-'; 449 date[7] = '-'; 450 date[10] = 'T'; 451 } 452 else { 453 free(date); 454 date = NULL; 455 } 456 } 457 else { 458 /* One last effort to get the date from XMP */ 459 image_get_jpeg_date_xmp(path, &date); 460 } 461 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", date); 462 463 e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE); 464 if( e ) 465 { 466 strncpy(make, exif_entry_get_value(e, b, sizeof(b)), sizeof(make)); 467 e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL); 468 if( e ) 469 { 470 strncpy(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model)); 471 if( !strcasestr(model, make) ) 472 snprintf(model, sizeof(model), "%s %s", make, exif_entry_get_value(e, b, sizeof(b))); 473 cam = strdup(model); 474 } 475 } 476 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model); 477 478 if( ed->size ) 479 { 480 /* We might need to verify that the thumbnail is 160x160 or smaller */ 481 if( ed->size > 12000 ) 482 { 483 imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size); 484 if( imsrc ) 485 { 486 if( (imsrc->width <= 160) && (imsrc->height <= 160) ) 487 { 488 thumb = 1; 489 } 490 image_free(imsrc); 491 } 492 } 493 else 494 { 495 thumb = 1; 496 } 497 } 498 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * thumbnail: %d\n", thumb); 499 500 exif_data_unref(ed); 501 502no_exifdata: 503 /* If SOF parsing fails, then fall through to reading the JPEG data with libjpeg to get the resolution */ 504 if( image_get_jpeg_resolution(path, &width, &height) != 0 || !width || !height ) 505 { 506 infile = fopen(path, "r"); 507 cinfo.err = jpeg_std_error(&jerr); 508 jerr.error_exit = libjpeg_error_handler; 509 jpeg_create_decompress(&cinfo); 510 if( setjmp(setjmp_buffer) ) 511 goto error; 512 jpeg_stdio_src(&cinfo, infile); 513 jpeg_read_header(&cinfo, TRUE); 514 jpeg_start_decompress(&cinfo); 515 width = cinfo.output_width; 516 height = cinfo.output_height; 517 error: 518 jpeg_destroy_decompress(&cinfo); 519 fclose(infile); 520 } 521 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * resolution: %dx%d\n", width, height); 522 523 if( !width || !height ) 524 { 525 if( m.mime ) 526 free(m.mime); 527 return 0; 528 } 529 if( width <= 640 && height <= 480 ) 530 asprintf(&m.dlna_pn, "JPEG_SM;%s", dlna_no_conv); 531 else if( width <= 1024 && height <= 768 ) 532 asprintf(&m.dlna_pn, "JPEG_MED;%s", dlna_no_conv); 533 else if( (width <= 4096 && height <= 4096) || !(GETFLAG(DLNA_STRICT_MASK)) ) 534 asprintf(&m.dlna_pn, "JPEG_LRG;%s", dlna_no_conv); 535 asprintf(&m.resolution, "%dx%d", width, height); 536 537 ret = sql_exec(db, "INSERT into DETAILS" 538 " (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION, THUMBNAIL, CREATOR, DLNA_PN, MIME) " 539 "VALUES" 540 " (%Q, '%q', %lld, %ld, %Q, %Q, %d, %Q, %Q, %Q);", 541 path, name, file.st_size, file.st_mtime, date, m.resolution, thumb, cam, m.dlna_pn, m.mime); 542 if( ret != SQLITE_OK ) 543 { 544 fprintf(stderr, "Error inserting details for '%s'!\n", path); 545 ret = 0; 546 } 547 else 548 { 549 ret = sqlite3_last_insert_rowid(db); 550 } 551 if( m.resolution ) 552 free(m.resolution); 553 if( m.dlna_pn ) 554 free(m.dlna_pn); 555 if( m.mime ) 556 free(m.mime); 557 if( date ) 558 free(date); 559 if( cam ) 560 free(cam); 561 return ret; 562} 563 564sqlite_int64 565GetVideoMetadata(const char * path, char * name) 566{ 567 struct stat file; 568 int ret, i; 569 struct tm *modtime; 570 char date[20]; 571 AVFormatContext *ctx; 572 int audio_stream = -1, video_stream = -1; 573 enum audio_profiles audio_profile = PROFILE_AUDIO_UNKNOWN; 574 ts_timestamp_t ts_timestamp = NONE; 575 int duration, hours, min, sec, ms; 576 aac_object_type_t aac_type = AAC_INVALID; 577 sqlite_int64 album_art = 0; 578 metadata_t m; 579 memset(&m, '\0', sizeof(m)); 580 date[0] = '\0'; 581 582 //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing video %s...\n", name); 583 if ( stat(path, &file) != 0 ) 584 return 0; 585 strip_ext(name); 586 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size); 587 588 modtime = localtime(&file.st_mtime); 589 strftime(date, sizeof(date), "%FT%T", modtime); 590 591 av_register_all(); 592 if( av_open_input_file(&ctx, path, NULL, 0, NULL) != 0 ) 593 { 594 DPRINTF(E_WARN, L_METADATA, "Opening %s failed!\n", path); 595 return 0; 596 } 597 av_find_stream_info(ctx); 598 //dump_format(ctx, 0, NULL, 0); 599 for( i=0; i<ctx->nb_streams; i++) 600 { 601 if( audio_stream == -1 && 602 ctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO ) 603 { 604 audio_stream = i; 605 continue; 606 } 607 else if( video_stream == -1 && 608 ctx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) 609 { 610 video_stream = i; 611 continue; 612 } 613 } 614 /* This must not be a video file. */ 615 if( video_stream == -1 ) 616 { 617 av_close_input_file(ctx); 618 if( !is_audio(path) ) 619 DPRINTF(E_DEBUG, L_METADATA, "File %s does not contain a video stream.\n", basename(path)); 620 return 0; 621 } 622 if( audio_stream >= 0 ) 623 { 624 switch( ctx->streams[audio_stream]->codec->codec_id ) 625 { 626 case CODEC_ID_MP3: 627 audio_profile = PROFILE_AUDIO_MP3; 628 break; 629 case CODEC_ID_AAC: 630 if( !ctx->streams[audio_stream]->codec->extradata_size || 631 !ctx->streams[audio_stream]->codec->extradata ) 632 { 633 DPRINTF(E_DEBUG, L_METADATA, "No AAC type\n"); 634 } 635 else 636 { 637 uint8_t data; 638 memcpy(&data, ctx->streams[audio_stream]->codec->extradata, 1); 639 aac_type = data >> 3; 640 } 641 switch( aac_type ) 642 { 643 /* AAC Low Complexity variants */ 644 case AAC_LC: 645 case AAC_LC_ER: 646 if( ctx->streams[audio_stream]->codec->sample_rate < 8000 || 647 ctx->streams[audio_stream]->codec->sample_rate > 48000 ) 648 { 649 DPRINTF(E_DEBUG, L_METADATA, "Unsupported AAC: sample rate is not 8000 < %d < 48000\n", 650 ctx->streams[audio_stream]->codec->sample_rate); 651 break; 652 } 653 /* AAC @ Level 1/2 */ 654 if( ctx->streams[audio_stream]->codec->channels <= 2 && 655 ctx->streams[audio_stream]->codec->bit_rate <= 576000 ) 656 audio_profile = PROFILE_AUDIO_AAC; 657 else if( ctx->streams[audio_stream]->codec->channels <= 6 && 658 ctx->streams[audio_stream]->codec->bit_rate <= 1440000 ) 659 audio_profile = PROFILE_AUDIO_AAC_MULT5; 660 else 661 DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC: %d channels, %d bitrate\n", 662 ctx->streams[audio_stream]->codec->channels, 663 ctx->streams[audio_stream]->codec->bit_rate); 664 break; 665 default: 666 DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC type [%d]\n", aac_type); 667 break; 668 } 669 break; 670 case CODEC_ID_AC3: 671 case CODEC_ID_DTS: 672 audio_profile = PROFILE_AUDIO_AC3; 673 break; 674 case CODEC_ID_WMAV1: 675 case CODEC_ID_WMAV2: 676 /* WMA Baseline: stereo, up to 48 KHz, up to 192,999 bps */ 677 if ( ctx->streams[audio_stream]->codec->bit_rate <= 193000 ) 678 audio_profile = PROFILE_AUDIO_WMA_BASE; 679 /* WMA Full: stereo, up to 48 KHz, up to 385 Kbps */ 680 else if ( ctx->streams[audio_stream]->codec->bit_rate <= 385000 ) 681 audio_profile = PROFILE_AUDIO_WMA_FULL; 682 break; 683 #if LIBAVCODEC_VERSION_INT > ((51<<16)+(50<<8)+1) 684 case CODEC_ID_WMAPRO: 685 audio_profile = PROFILE_AUDIO_WMA_PRO; 686 break; 687 #endif 688 case CODEC_ID_MP2: 689 audio_profile = PROFILE_AUDIO_MP2; 690 break; 691 case CODEC_ID_AMR_NB: 692 audio_profile = PROFILE_AUDIO_AMR; 693 break; 694 default: 695 if( (ctx->streams[audio_stream]->codec->codec_id >= CODEC_ID_PCM_S16LE) && 696 (ctx->streams[audio_stream]->codec->codec_id < CODEC_ID_ADPCM_IMA_QT) ) 697 audio_profile = PROFILE_AUDIO_PCM; 698 else 699 DPRINTF(E_DEBUG, L_METADATA, "Unhandled audio codec [0x%X]\n", ctx->streams[audio_stream]->codec->codec_id); 700 break; 701 } 702 asprintf(&m.frequency, "%u", ctx->streams[audio_stream]->codec->sample_rate); 703 #if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0) 704 asprintf(&m.bps, "%u", ctx->streams[audio_stream]->codec->bits_per_sample); 705 #else 706 asprintf(&m.bps, "%u", ctx->streams[audio_stream]->codec->bits_per_coded_sample); 707 #endif 708 asprintf(&m.channels, "%u", ctx->streams[audio_stream]->codec->channels); 709 } 710 if( video_stream >= 0 ) 711 { 712 DPRINTF(E_DEBUG, L_METADATA, "Container: '%s' [%s]\n", ctx->iformat->name, basename(path)); 713 asprintf(&m.resolution, "%dx%d", ctx->streams[video_stream]->codec->width, ctx->streams[video_stream]->codec->height); 714 if( ctx->bit_rate > 8 ) 715 asprintf(&m.bitrate, "%u", ctx->bit_rate / 8); 716 if( ctx->duration > 0 ) { 717 duration = (int)(ctx->duration / AV_TIME_BASE); 718 hours = (int)(duration / 3600); 719 min = (int)(duration / 60 % 60); 720 sec = (int)(duration % 60); 721 ms = (int)(ctx->duration / (AV_TIME_BASE/1000) % 1000); 722 asprintf(&m.duration, "%d:%02d:%02d.%03d", hours, min, sec, ms); 723 } 724 /* NOTE: The DLNA spec only provides for ASF (WMV), TS, PS, and MP4 containers -- not AVI. */ 725 switch( ctx->streams[video_stream]->codec->codec_id ) 726 { 727 case CODEC_ID_MPEG1VIDEO: 728 if( strcmp(ctx->iformat->name, "mpeg") == 0 ) 729 { 730 if( (ctx->streams[video_stream]->codec->width == 352) && 731 (ctx->streams[video_stream]->codec->height <= 288) ) 732 { 733 asprintf(&m.dlna_pn, "MPEG1;%s", dlna_no_conv); 734 } 735 asprintf(&m.mime, "video/mpeg"); 736 } 737 break; 738 case CODEC_ID_MPEG2VIDEO: 739 if( strcmp(ctx->iformat->name, "mpegts") == 0 ) 740 { 741 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s MPEG2 TS\n", video_stream, basename(path), m.resolution); 742 char res; 743 tsinfo_t * ts = ctx->priv_data; 744 if( ts->packet_size == 192 ) 745 { 746 asprintf(&m.dlna_pn, "MPEG_TS_HD_NA;%s", dlna_no_conv); 747 asprintf(&m.mime, "video/vnd.dlna.mpeg-tts"); 748 } 749 else if( ts->packet_size == 188 ) 750 { 751 if( (ctx->streams[video_stream]->codec->width >= 1280) && 752 (ctx->streams[video_stream]->codec->height >= 720) ) 753 res = 'H'; 754 else 755 res = 'S'; 756 asprintf(&m.dlna_pn, "MPEG_TS_%cD_NA_ISO;%s", res, dlna_no_conv); 757 asprintf(&m.mime, "video/mpeg"); 758 } 759 } 760 else if( strcmp(ctx->iformat->name, "mpeg") == 0 ) 761 { 762 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s MPEG2 PS\n", video_stream, basename(path), m.resolution); 763 char region[5]; 764 if( (ctx->streams[video_stream]->codec->height == 576) || 765 (ctx->streams[video_stream]->codec->height == 288) ) 766 strcpy(region, "PAL"); 767 else 768 strcpy(region, "NTSC"); 769 asprintf(&m.dlna_pn, "MPEG_PS_%s;%s", region, dlna_no_conv); 770 asprintf(&m.mime, "video/mpeg"); 771 } 772 else 773 { 774 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s [UNKNOWN CONTAINER] is %s MPEG2\n", video_stream, basename(path), m.resolution); 775 } 776 break; 777 case CODEC_ID_H264: 778 if( strcmp(ctx->iformat->name, "mpegts") == 0 ) 779 { 780 tsinfo_t * ts = ctx->priv_data; 781 if( ts->packet_size == 192 ) 782 { 783 if( dlna_timestamp_is_present(path) ) 784 ts_timestamp = VALID; 785 else 786 ts_timestamp = EMPTY; 787 } 788 char res = '\0'; 789 if( ctx->streams[video_stream]->codec->width <= 720 && 790 ctx->streams[video_stream]->codec->height <= 576 && 791 ctx->streams[video_stream]->codec->bit_rate <= 10000000 ) 792 res = 'S'; 793 else if( ctx->streams[video_stream]->codec->width <= 1920 && 794 ctx->streams[video_stream]->codec->height <= 1152 && 795 ctx->streams[video_stream]->codec->bit_rate <= 20000000 ) 796 res = 'H'; 797 if( res ) 798 { 799 switch( audio_profile ) 800 { 801 case PROFILE_AUDIO_MP3: 802 asprintf(&m.dlna_pn, "AVC_TS_MP_HD_MPEG1_L3%s;%s", 803 ts_timestamp==NONE?"_ISO" : ts_timestamp==VALID?"_T":"", dlna_no_conv); 804 break; 805 case PROFILE_AUDIO_AC3: 806 asprintf(&m.dlna_pn, "AVC_TS_MP_HD_AC3%s;%s", 807 ts_timestamp==NONE?"_ISO" : ts_timestamp==VALID?"_T":"", dlna_no_conv); 808 break; 809 case PROFILE_AUDIO_AAC_MULT5: 810 asprintf(&m.dlna_pn, "AVC_TS_MP_HD_AAC_MULT5%s;%s", 811 ts_timestamp==NONE?"_ISO" : ts_timestamp==VALID?"_T":"", dlna_no_conv); 812 break; 813 default: 814 DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for TS/AVC/%cD file %s\n", res, basename(path)); 815 break; 816 } 817 if( m.dlna_pn && (ts_timestamp != NONE) ) 818 asprintf(&m.mime, "video/vnd.dlna.mpeg-tts"); 819 } 820 else 821 { 822 DPRINTF(E_DEBUG, L_METADATA, "Unsupported h.264 video profile! [%dx%d, %dbps]\n", 823 ctx->streams[video_stream]->codec->width, 824 ctx->streams[video_stream]->codec->height, 825 ctx->streams[video_stream]->codec->bit_rate); 826 } 827 } 828 else if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 ) 829 { 830 /* AVC wrapped in MP4 only has SD profiles - 10 Mbps max */ 831 if( ctx->streams[video_stream]->codec->width <= 720 && 832 ctx->streams[video_stream]->codec->height <= 576 && 833 ctx->streams[video_stream]->codec->bit_rate <= 10000000 && 834 !ends_with(path, ".mov") ) 835 { 836 switch( audio_profile ) 837 { 838 case PROFILE_AUDIO_AC3: 839 asprintf(&m.dlna_pn, "AVC_MP4_MP_SD_AC3;%s", dlna_no_conv); 840 break; 841 case PROFILE_AUDIO_AAC_MULT5: 842 asprintf(&m.dlna_pn, "AVC_MP4_MP_SD_AAC_MULT5;%s", dlna_no_conv); 843 break; 844 default: 845 DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for MP4/AVC/SD file %s\n", basename(path)); 846 break; 847 } 848 } 849 } 850 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is h.264\n", video_stream, basename(path)); 851 break; 852 case CODEC_ID_MPEG4: 853 if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("XVID") ) 854 { 855 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s XViD\n", video_stream, basename(path), m.resolution); 856 asprintf(&m.artist, "DiVX"); 857 } 858 else if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("DX50") ) 859 { 860 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s DiVX5\n", video_stream, basename(path), m.resolution); 861 asprintf(&m.artist, "DiVX"); 862 } 863 else if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("DIVX") ) 864 { 865 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is DiVX\n", video_stream, basename(path)); 866 asprintf(&m.artist, "DiVX"); 867 } 868 else if( ends_with(path, ".3gp") && (strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0) ) 869 { 870 asprintf(&m.mime, "video/3gpp"); 871 switch( audio_profile ) 872 { 873 case PROFILE_AUDIO_AAC: 874 asprintf(&m.dlna_pn, "MPEG4_P2_3GPP_SP_L0B_AAC;%s", dlna_no_conv); 875 break; 876 case PROFILE_AUDIO_AMR: 877 asprintf(&m.dlna_pn, "MPEG4_P2_3GPP_SP_L0B_AMR;%s", dlna_no_conv); 878 break; 879 default: 880 DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for MPEG4-P2 3GP/0x%X file %s\n", 881 ctx->streams[audio_stream]->codec->codec_id, basename(path)); 882 break; 883 } 884 } 885 else 886 { 887 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is MPEG4 [%X]\n", video_stream, basename(path), ctx->streams[video_stream]->codec->codec_tag); 888 } 889 break; 890 case CODEC_ID_WMV3: 891 case CODEC_ID_VC1: 892 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is VC1\n", video_stream, basename(path)); 893 char profile[5]; profile[0] = '\0'; 894 asprintf(&m.mime, "video/x-ms-wmv"); 895 if( (ctx->streams[video_stream]->codec->width <= 352) && 896 (ctx->streams[video_stream]->codec->height <= 288) && 897 (ctx->bit_rate/8 <= 384000) ) 898 { 899 switch( audio_profile ) 900 { 901 case PROFILE_AUDIO_MP3: 902 asprintf(&m.dlna_pn, "WMVSPML_MP3;%s", dlna_no_conv); 903 break; 904 case PROFILE_AUDIO_WMA_BASE: 905 asprintf(&m.dlna_pn, "WMVSPML_BASE;%s", dlna_no_conv); 906 break; 907 default: 908 DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for WMVSPML/0x%X file %s\n", audio_profile, basename(path)); 909 break; 910 } 911 } 912 else if( (ctx->streams[video_stream]->codec->width <= 720) && 913 (ctx->streams[video_stream]->codec->height <= 576) && 914 (ctx->bit_rate/8 <= 10000000) ) 915 { 916 switch( audio_profile ) 917 { 918 case PROFILE_AUDIO_WMA_PRO: 919 asprintf(&m.dlna_pn, "WMVMED_PRO;%s", dlna_no_conv); 920 break; 921 case PROFILE_AUDIO_WMA_FULL: 922 asprintf(&m.dlna_pn, "WMVMED_FULL;%s", dlna_no_conv); 923 break; 924 case PROFILE_AUDIO_WMA_BASE: 925 asprintf(&m.dlna_pn, "WMVMED_BASE;%s", dlna_no_conv); 926 break; 927 default: 928 DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for WMVMED/0x%X file %s\n", audio_profile, basename(path)); 929 break; 930 } 931 } 932 else if( (ctx->streams[video_stream]->codec->width <= 1920) && 933 (ctx->streams[video_stream]->codec->height <= 1080) && 934 (ctx->bit_rate/8 <= 20000000) ) 935 { 936 switch( audio_profile ) 937 { 938 case PROFILE_AUDIO_WMA_PRO: 939 asprintf(&m.dlna_pn, "WMVHIGH_PRO;%s", dlna_no_conv); 940 break; 941 case PROFILE_AUDIO_WMA_FULL: 942 asprintf(&m.dlna_pn, "WMVHIGH_FULL;%s", dlna_no_conv); 943 break; 944 default: 945 DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for WMVHIGH/0x%X file %s\n", audio_profile, basename(path)); 946 break; 947 } 948 } 949 break; 950 case CODEC_ID_MSMPEG4V3: 951 asprintf(&m.mime, "video/x-msvideo"); 952 default: 953 DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s [type %d]\n", video_stream, basename(path), m.resolution, ctx->streams[video_stream]->codec->codec_id); 954 break; 955 } 956 } 957 if( !m.mime ) 958 { 959 if( strcmp(ctx->iformat->name, "avi") == 0 ) 960 asprintf(&m.mime, "video/x-msvideo"); 961 else if( strcmp(ctx->iformat->name, "mpegts") == 0 ) 962 asprintf(&m.mime, "video/mpeg"); 963 else if( strcmp(ctx->iformat->name, "mpeg") == 0 ) 964 asprintf(&m.mime, "video/mpeg"); 965 else if( strcmp(ctx->iformat->name, "asf") == 0 ) 966 asprintf(&m.mime, "video/x-ms-wmv"); 967 else if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 ) 968 if( ends_with(path, ".mov") ) 969 asprintf(&m.mime, "video/quicktime"); 970 else 971 asprintf(&m.mime, "video/mp4"); 972 else if( strcmp(ctx->iformat->name, "matroska") == 0 ) 973 asprintf(&m.mime, "video/x-matroska"); 974 else if( strcmp(ctx->iformat->name, "flv") == 0 ) 975 asprintf(&m.mime, "video/x-flv"); 976 else 977 DPRINTF(E_WARN, L_METADATA, "%s: Unhandled format: %s\n", path, ctx->iformat->name); 978 } 979 av_close_input_file(ctx); 980#ifdef TIVO_SUPPORT 981 if( ends_with(path, ".TiVo") && is_tivo_file(path) ) 982 { 983 free(m.mime); 984 asprintf(&m.mime, "video/x-tivo-mpeg"); 985 } 986#endif 987 album_art = find_album_art(path, NULL, 0); 988 989 ret = sql_exec(db, "INSERT into DETAILS" 990 " (PATH, SIZE, TIMESTAMP, DURATION, DATE, CHANNELS, BITRATE, SAMPLERATE, RESOLUTION," 991 " CREATOR, TITLE, DLNA_PN, MIME, ALBUM_ART) " 992 "VALUES" 993 " (%Q, %lld, %ld, %Q, %Q, %Q, %Q, %Q, %Q, %Q, '%q', %Q, '%q', %lld);", 994 path, file.st_size, file.st_mtime, m.duration, 995 strlen(date) ? date : NULL, 996 m.channels, m.bitrate, m.frequency, m.resolution, 997 m.artist, name, m.dlna_pn, m.mime, album_art); 998 if( ret != SQLITE_OK ) 999 { 1000 fprintf(stderr, "Error inserting details for '%s'!\n", path); 1001 ret = 0; 1002 } 1003 else 1004 { 1005 ret = sqlite3_last_insert_rowid(db); 1006 check_for_captions(path, ret); 1007 } 1008 if( m.dlna_pn ) 1009 free(m.dlna_pn); 1010 if( m.mime ) 1011 free(m.mime); 1012 if( m.duration ) 1013 free(m.duration); 1014 if( m.resolution ) 1015 free(m.resolution); 1016 if( m.bitrate ) 1017 free(m.bitrate); 1018 if( m.frequency ) 1019 free(m.frequency); 1020 if( m.bps ) 1021 free(m.bps); 1022 if( m.channels ) 1023 free(m.channels); 1024 if( m.artist ) 1025 free(m.artist); 1026 1027 return ret; 1028} 1029