1 /* MiniDLNA media server
2 * Copyright (C) 2008-2009 Justin Maggard
4 * This file is part of MiniDLNA.
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.
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.
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/>.
25 #include <sys/types.h>
29 #include <libexif/exif-loader.h>
30 #include "image_utils.h"
36 #include "tagutils/tagutils.h"
38 #include "upnpglobalvars.h"
39 #include "upnpreplyparse.h"
46 #ifndef FF_PROFILE_H264_BASELINE
47 #define FF_PROFILE_H264_BASELINE 66
49 #ifndef FF_PROFILE_H264_MAIN
50 #define FF_PROFILE_H264_MAIN 77
52 #ifndef FF_PROFILE_H264_HIGH
53 #define FF_PROFILE_H264_HIGH 100
56 #define FLAG_TITLE 0x00000001
57 #define FLAG_ARTIST 0x00000002
58 #define FLAG_ALBUM 0x00000004
59 #define FLAG_GENRE 0x00000008
60 #define FLAG_COMMENT 0x00000010
61 #define FLAG_CREATOR 0x00000020
62 #define FLAG_DATE 0x00000040
63 #define FLAG_DLNA_PN 0x00000080
64 #define FLAG_MIME 0x00000100
65 #define FLAG_DURATION 0x00000200
66 #define FLAG_RESOLUTION 0x00000400
67 #define FLAG_BITRATE 0x00000800
68 #define FLAG_FREQUENCY 0x00001000
69 #define FLAG_BPS 0x00002000
70 #define FLAG_CHANNELS 0x00004000
72 /* Audio profile flags */
74 PROFILE_AUDIO_UNKNOWN
,
77 PROFILE_AUDIO_WMA_BASE
,
78 PROFILE_AUDIO_WMA_FULL
,
79 PROFILE_AUDIO_WMA_PRO
,
83 PROFILE_AUDIO_AAC_MULT5
,
87 /* This function shamelessly copied from libdlna */
88 #define MPEG_TS_SYNC_CODE 0x47
89 #define MPEG_TS_PACKET_LENGTH 188 /* prepends 4 bytes to TS packet */
90 #define MPEG_TS_PACKET_LENGTH_DLNA 192 /* prepends 4 bytes to TS packet */
92 dlna_timestamp_is_present(const char * filename
)
94 unsigned char buffer
[2*MPEG_TS_PACKET_LENGTH_DLNA
+1];
97 /* read file header */
98 fd
= open(filename
, O_RDONLY
);
99 read(fd
, buffer
, MPEG_TS_PACKET_LENGTH_DLNA
*2);
101 for( i
=0; i
< MPEG_TS_PACKET_LENGTH_DLNA
; i
++ )
103 if( buffer
[i
] == MPEG_TS_SYNC_CODE
)
105 if (buffer
[i
+ MPEG_TS_PACKET_LENGTH_DLNA
] == MPEG_TS_SYNC_CODE
)
107 if (buffer
[i
+MPEG_TS_PACKET_LENGTH
] == 0x00 &&
108 buffer
[i
+MPEG_TS_PACKET_LENGTH
+1] == 0x00 &&
109 buffer
[i
+MPEG_TS_PACKET_LENGTH
+2] == 0x00 &&
110 buffer
[i
+MPEG_TS_PACKET_LENGTH
+3] == 0x00)
122 is_tivo_file(const char * path
)
124 unsigned char buf
[5];
125 unsigned char hdr
[5] = { 'T','i','V','o','\0' };
128 /* read file header */
129 fd
= open(path
, O_RDONLY
);
133 return( !memcmp(buf
, hdr
, 5) );
138 check_for_captions(const char * path
, sqlite_int64 detailID
)
140 char *file
= malloc(PATH_MAX
);
143 sprintf(file
, "%s", path
);
146 /* If we weren't given a detail ID, look for one. */
149 id
= sql_get_text_field(db
, "SELECT ID from DETAILS where PATH glob '%q.*'"
150 " and MIME glob 'video/*' limit 1", file
);
153 //DEBUG DPRINTF(E_DEBUG, L_METADATA, "New file %s looks like a caption file.\n", path);
154 detailID
= strtoll(id
, NULL
, 10);
158 //DPRINTF(E_DEBUG, L_METADATA, "No file found for caption %s.\n", path);
159 goto no_source_video
;
163 strcat(file
, ".srt");
164 if( access(file
, R_OK
) == 0 )
166 sql_exec(db
, "INSERT into CAPTIONS"
169 " (%lld, %Q)", detailID
, file
);
178 parse_nfo(const char * path
, metadata_t
* m
)
182 struct NameValueParserData xml
;
187 if( stat(path
, &file
) != 0 ||
188 file
.st_size
> 65536 )
190 DPRINTF(E_INFO
, L_METADATA
, "Not parsing very large .nfo file %s\n", path
);
193 DPRINTF(E_DEBUG
, L_METADATA
, "Parsing .nfo file: %s\n", path
);
194 nfo
= fopen(path
, "r");
197 nread
= fread(&buf
, 1, sizeof(buf
), nfo
);
199 ParseNameValue(buf
, nread
, &xml
);
201 //printf("\ttype: %s\n", GetValueFromNameValueList(&xml, "rootElement"));
202 val
= GetValueFromNameValueList(&xml
, "title");
205 val2
= GetValueFromNameValueList(&xml
, "episodetitle");
207 asprintf(&m
->title
, "%s - %s", val
, val2
);
209 m
->title
= strdup(val
);
212 val
= GetValueFromNameValueList(&xml
, "plot");
214 m
->comment
= strdup(val
);
216 val
= GetValueFromNameValueList(&xml
, "capturedate");
218 m
->date
= strdup(val
);
220 val
= GetValueFromNameValueList(&xml
, "genre");
222 m
->genre
= strdup(val
);
224 ClearNameValueList(&xml
);
229 free_metadata(metadata_t
* m
, uint32_t flags
)
231 if( m
->title
&& (flags
& FLAG_TITLE
) )
233 if( m
->artist
&& (flags
& FLAG_ARTIST
) )
235 if( m
->album
&& (flags
& FLAG_ALBUM
) )
237 if( m
->genre
&& (flags
& FLAG_GENRE
) )
239 if( m
->creator
&& (flags
& FLAG_CREATOR
) )
241 if( m
->date
&& (flags
& FLAG_DATE
) )
243 if( m
->comment
&& (flags
& FLAG_COMMENT
) )
245 if( m
->dlna_pn
&& (flags
& FLAG_DLNA_PN
) )
247 if( m
->mime
&& (flags
& FLAG_MIME
) )
249 if( m
->duration
&& (flags
& FLAG_DURATION
) )
251 if( m
->resolution
&& (flags
& FLAG_RESOLUTION
) )
253 if( m
->bitrate
&& (flags
& FLAG_BITRATE
) )
255 if( m
->frequency
&& (flags
& FLAG_FREQUENCY
) )
257 if( m
->bps
&& (flags
& FLAG_BPS
) )
259 if( m
->channels
&& (flags
& FLAG_CHANNELS
) )
264 GetFolderMetadata(const char * name
, const char * path
, const char * artist
, const char * genre
, const char * album_art
)
268 ret
= sql_exec(db
, "INSERT into DETAILS"
269 " (TITLE, PATH, CREATOR, ARTIST, GENRE, ALBUM_ART) "
271 " ('%q', %Q, %Q, %Q, %Q, %lld);",
272 name
, path
, artist
, artist
, genre
,
273 album_art
? strtoll(album_art
, NULL
, 10) : 0);
274 if( ret
!= SQLITE_OK
)
277 ret
= sqlite3_last_insert_rowid(db
);
283 GetAudioMetadata(const char * path
, char * name
)
286 static char lang
[6] = { '\0' };
291 sqlite_int64 album_art
= 0;
292 struct song_metadata song
;
294 uint32_t free_flags
= FLAG_MIME
|FLAG_DURATION
|FLAG_DLNA_PN
|FLAG_DATE
;
295 memset(&m
, '\0', sizeof(metadata_t
));
297 if ( stat(path
, &file
) != 0 )
301 if( ends_with(path
, ".mp3") )
304 m
.mime
= strdup("audio/mpeg");
306 else if( ends_with(path
, ".m4a") || ends_with(path
, ".mp4") ||
307 ends_with(path
, ".aac") || ends_with(path
, ".m4p") )
310 m
.mime
= strdup("audio/mp4");
312 else if( ends_with(path
, ".3gp") )
315 m
.mime
= strdup("audio/3gpp");
317 else if( ends_with(path
, ".wma") || ends_with(path
, ".asf") )
320 m
.mime
= strdup("audio/x-ms-wma");
322 else if( ends_with(path
, ".flac") || ends_with(path
, ".fla") || ends_with(path
, ".flc") )
325 m
.mime
= strdup("audio/x-flac");
327 else if( ends_with(path
, ".wav") )
330 m
.mime
= strdup("audio/x-wav");
332 else if( ends_with(path
, ".ogg") || ends_with(path
, ".oga") )
335 m
.mime
= strdup("audio/ogg");
337 else if( ends_with(path
, ".pcm") )
340 m
.mime
= strdup("audio/L16");
344 DPRINTF(E_WARN
, L_GENERAL
, "Unhandled file extension on %s\n", path
);
350 if( !getenv("LANG") )
351 strcpy(lang
, "en_US");
353 strncpy(lang
, getenv("LANG"), 5);
357 if( readtags((char *)path
, &song
, &file
, lang
, type
) != 0 )
359 DPRINTF(E_WARN
, L_GENERAL
, "Cannot extract tags from %s!\n", path
);
361 free_metadata(&m
, free_flags
);
366 asprintf(&m
.dlna_pn
, "%s;DLNA.ORG_OP=01;DLNA.ORG_CI=0", song
.dlna_pn
);
368 asprintf(&m
.date
, "%04d-01-01", song
.year
);
369 asprintf(&m
.duration
, "%d:%02d:%02d.%03d",
370 (song
.song_length
/3600000),
371 (song
.song_length
/60000%60),
372 (song
.song_length
/1000%60),
373 (song
.song_length
%1000));
374 if( song
.title
&& *song
.title
)
376 m
.title
= trim(song
.title
);
377 if( (esc_tag
= escape_tag(m
.title
, 0)) )
379 free_flags
|= FLAG_TITLE
;
387 for( i
=ROLE_START
; i
<N_ROLE
; i
++ )
389 if( song
.contributor
[i
] && *song
.contributor
[i
] )
391 m
.creator
= trim(song
.contributor
[i
]);
392 if( strlen(m
.creator
) > 48 )
394 m
.creator
= strdup("Various Artists");
395 free_flags
|= FLAG_CREATOR
;
397 else if( (esc_tag
= escape_tag(m
.creator
, 0)) )
400 free_flags
|= FLAG_CREATOR
;
402 m
.artist
= m
.creator
;
406 /* If there is a band associated with the album, use it for virtual containers. */
407 if( (i
!= ROLE_BAND
) && (i
!= ROLE_ALBUMARTIST
) )
409 if( song
.contributor
[ROLE_BAND
] && *song
.contributor
[ROLE_BAND
] )
412 m
.artist
= trim(song
.contributor
[i
]);
413 if( strlen(m
.artist
) > 48 )
415 m
.artist
= strdup("Various Artists");
416 free_flags
|= FLAG_ARTIST
;
418 else if( (esc_tag
= escape_tag(m
.artist
, 0)) )
421 free_flags
|= FLAG_ARTIST
;
425 if( song
.album
&& *song
.album
)
427 m
.album
= trim(song
.album
);
428 if( (esc_tag
= escape_tag(m
.album
, 0)) )
430 free_flags
|= FLAG_ALBUM
;
434 if( song
.genre
&& *song
.genre
)
436 m
.genre
= trim(song
.genre
);
437 if( (esc_tag
= escape_tag(m
.genre
, 0)) )
439 free_flags
|= FLAG_GENRE
;
443 if( song
.comment
&& *song
.comment
)
445 m
.comment
= trim(song
.comment
);
446 if( (esc_tag
= escape_tag(m
.comment
, 0)) )
448 free_flags
|= FLAG_COMMENT
;
453 album_art
= find_album_art(path
, song
.image
, song
.image_size
);
455 ret
= sql_exec(db
, "INSERT into DETAILS"
456 " (PATH, SIZE, TIMESTAMP, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE,"
457 " TITLE, CREATOR, ARTIST, ALBUM, GENRE, COMMENT, DISC, TRACK, DLNA_PN, MIME, ALBUM_ART) "
459 " (%Q, %lld, %ld, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, %d, %Q, '%s', %lld);",
460 path
, file
.st_size
, file
.st_mtime
, m
.duration
, song
.channels
, song
.bitrate
, song
.samplerate
, m
.date
,
461 m
.title
, m
.creator
, m
.artist
, m
.album
, m
.genre
, m
.comment
, song
.disc
, song
.track
,
462 m
.dlna_pn
, song
.mime
?song
.mime
:m
.mime
, album_art
);
463 if( ret
!= SQLITE_OK
)
465 fprintf(stderr
, "Error inserting details for '%s'!\n", path
);
470 ret
= sqlite3_last_insert_rowid(db
);
473 free_metadata(&m
, free_flags
);
478 /* For libjpeg error handling */
479 jmp_buf setjmp_buffer
;
481 libjpeg_error_handler(j_common_ptr cinfo
)
483 cinfo
->err
->output_message (cinfo
);
484 longjmp(setjmp_buffer
, 1);
489 GetImageMetadata(const char * path
, char * name
)
494 struct jpeg_decompress_struct cinfo
;
495 struct jpeg_error_mgr jerr
;
497 int width
=0, height
=0, thumb
=0;
498 char make
[32], model
[64] = {'\0'};
504 uint32_t free_flags
= 0xFFFFFFFF;
505 memset(&m
, '\0', sizeof(metadata_t
));
507 //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path);
508 if ( stat(path
, &file
) != 0 )
511 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size);
513 /* MIME hard-coded to JPEG for now, until we add PNG support */
514 asprintf(&m
.mime
, "image/jpeg");
516 l
= exif_loader_new();
517 exif_loader_write_file(l
, path
);
518 ed
= exif_loader_get_data(l
);
519 exif_loader_unref(l
);
523 e
= exif_content_get_entry (ed
->ifd
[EXIF_IFD_EXIF
], EXIF_TAG_DATE_TIME_ORIGINAL
);
524 if( e
|| (e
= exif_content_get_entry(ed
->ifd
[EXIF_IFD_EXIF
], EXIF_TAG_DATE_TIME_DIGITIZED
)) ) {
525 m
.date
= strdup(exif_entry_get_value(e
, b
, sizeof(b
)));
526 if( strlen(m
.date
) > 10 )
538 /* One last effort to get the date from XMP */
539 image_get_jpeg_date_xmp(path
, &m
.date
);
541 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", m.date);
543 e
= exif_content_get_entry (ed
->ifd
[EXIF_IFD_0
], EXIF_TAG_MAKE
);
546 strncpy(make
, exif_entry_get_value(e
, b
, sizeof(b
)), sizeof(make
));
547 e
= exif_content_get_entry (ed
->ifd
[EXIF_IFD_0
], EXIF_TAG_MODEL
);
550 strncpy(model
, exif_entry_get_value(e
, b
, sizeof(b
)), sizeof(model
));
551 if( !strcasestr(model
, make
) )
552 snprintf(model
, sizeof(model
), "%s %s", make
, exif_entry_get_value(e
, b
, sizeof(b
)));
553 m
.creator
= strdup(model
);
556 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model);
560 /* We might need to verify that the thumbnail is 160x160 or smaller */
561 if( ed
->size
> 12000 )
563 imsrc
= image_new_from_jpeg(NULL
, 0, (char *)ed
->data
, ed
->size
, 1);
566 if( (imsrc
->width
<= 160) && (imsrc
->height
<= 160) )
574 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * thumbnail: %d\n", thumb);
579 /* If SOF parsing fails, then fall through to reading the JPEG data with libjpeg to get the resolution */
580 if( image_get_jpeg_resolution(path
, &width
, &height
) != 0 || !width
|| !height
)
582 infile
= fopen(path
, "r");
583 cinfo
.err
= jpeg_std_error(&jerr
);
584 jerr
.error_exit
= libjpeg_error_handler
;
585 jpeg_create_decompress(&cinfo
);
586 if( setjmp(setjmp_buffer
) )
588 jpeg_stdio_src(&cinfo
, infile
);
589 jpeg_read_header(&cinfo
, TRUE
);
590 jpeg_start_decompress(&cinfo
);
591 width
= cinfo
.output_width
;
592 height
= cinfo
.output_height
;
594 jpeg_destroy_decompress(&cinfo
);
597 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * resolution: %dx%d\n", width, height);
599 if( !width
|| !height
)
601 free_metadata(&m
, free_flags
);
604 if( width
<= 640 && height
<= 480 )
605 asprintf(&m
.dlna_pn
, "JPEG_SM;%s", dlna_no_conv
);
606 else if( width
<= 1024 && height
<= 768 )
607 asprintf(&m
.dlna_pn
, "JPEG_MED;%s", dlna_no_conv
);
608 else if( (width
<= 4096 && height
<= 4096) || !(GETFLAG(DLNA_STRICT_MASK
)) )
609 asprintf(&m
.dlna_pn
, "JPEG_LRG;%s", dlna_no_conv
);
610 asprintf(&m
.resolution
, "%dx%d", width
, height
);
612 ret
= sql_exec(db
, "INSERT into DETAILS"
613 " (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION, THUMBNAIL, CREATOR, DLNA_PN, MIME) "
615 " (%Q, '%q', %lld, %ld, %Q, %Q, %d, %Q, %Q, %Q);",
616 path
, name
, file
.st_size
, file
.st_mtime
, m
.date
, m
.resolution
, thumb
, m
.creator
, m
.dlna_pn
, m
.mime
);
617 if( ret
!= SQLITE_OK
)
619 fprintf(stderr
, "Error inserting details for '%s'!\n", path
);
624 ret
= sqlite3_last_insert_rowid(db
);
626 free_metadata(&m
, free_flags
);
632 GetVideoMetadata(const char * path
, char * name
)
637 AVFormatContext
*ctx
;
638 AVCodecContext
*ac
= NULL
, *vc
= NULL
;
639 int audio_stream
= -1, video_stream
= -1;
640 enum audio_profiles audio_profile
= PROFILE_AUDIO_UNKNOWN
;
643 sqlite_int64 album_art
= 0;
644 char nfo
[PATH_MAX
], *ext
;
645 struct song_metadata video
;
647 uint32_t free_flags
= 0xFFFFFFFF;
648 memset(&m
, '\0', sizeof(m
));
649 memset(&video
, '\0', sizeof(video
));
651 //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing video %s...\n", name);
652 if ( stat(path
, &file
) != 0 )
655 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size);
658 if( av_open_input_file(&ctx
, path
, NULL
, 0, NULL
) != 0 )
660 DPRINTF(E_WARN
, L_METADATA
, "Opening %s failed!\n", path
);
663 av_find_stream_info(ctx
);
664 //dump_format(ctx, 0, NULL, 0);
665 for( i
=0; i
<ctx
->nb_streams
; i
++)
667 if( audio_stream
== -1 &&
668 ctx
->streams
[i
]->codec
->codec_type
== CODEC_TYPE_AUDIO
)
671 ac
= ctx
->streams
[audio_stream
]->codec
;
674 else if( video_stream
== -1 &&
675 ctx
->streams
[i
]->codec
->codec_type
== CODEC_TYPE_VIDEO
)
678 vc
= ctx
->streams
[video_stream
]->codec
;
682 /* This must not be a video file. */
685 av_close_input_file(ctx
);
686 if( !is_audio(path
) )
687 DPRINTF(E_DEBUG
, L_METADATA
, "File %s does not contain a video stream.\n", basename(path
));
692 ext
= strrchr(nfo
, '.');
695 strcpy(ext
+1, "nfo");
696 if( access(nfo
, F_OK
) == 0 )
705 modtime
= localtime(&file
.st_mtime
);
706 strftime(m
.date
, 20, "%FT%T", modtime
);
711 aac_object_type_t aac_type
= AAC_INVALID
;
712 switch( ac
->codec_id
)
715 audio_profile
= PROFILE_AUDIO_MP3
;
718 if( !ac
->extradata_size
||
721 DPRINTF(E_DEBUG
, L_METADATA
, "No AAC type\n");
726 memcpy(&data
, ac
->extradata
, 1);
727 aac_type
= data
>> 3;
731 /* AAC Low Complexity variants */
734 if( ac
->sample_rate
< 8000 ||
735 ac
->sample_rate
> 48000 )
737 DPRINTF(E_DEBUG
, L_METADATA
, "Unsupported AAC: sample rate is not 8000 < %d < 48000\n",
741 /* AAC @ Level 1/2 */
742 if( ac
->channels
<= 2 &&
743 ac
->bit_rate
<= 576000 )
744 audio_profile
= PROFILE_AUDIO_AAC
;
745 else if( ac
->channels
<= 6 &&
746 ac
->bit_rate
<= 1440000 )
747 audio_profile
= PROFILE_AUDIO_AAC_MULT5
;
749 DPRINTF(E_DEBUG
, L_METADATA
, "Unhandled AAC: %d channels, %d bitrate\n",
754 DPRINTF(E_DEBUG
, L_METADATA
, "Unhandled AAC type [%d]\n", aac_type
);
760 audio_profile
= PROFILE_AUDIO_AC3
;
764 /* WMA Baseline: stereo, up to 48 KHz, up to 192,999 bps */
765 if ( ac
->bit_rate
<= 193000 )
766 audio_profile
= PROFILE_AUDIO_WMA_BASE
;
767 /* WMA Full: stereo, up to 48 KHz, up to 385 Kbps */
768 else if ( ac
->bit_rate
<= 385000 )
769 audio_profile
= PROFILE_AUDIO_WMA_FULL
;
771 #if LIBAVCODEC_VERSION_INT > ((51<<16)+(50<<8)+1)
772 case CODEC_ID_WMAPRO
:
773 audio_profile
= PROFILE_AUDIO_WMA_PRO
;
777 audio_profile
= PROFILE_AUDIO_MP2
;
779 case CODEC_ID_AMR_NB
:
780 audio_profile
= PROFILE_AUDIO_AMR
;
783 if( (ac
->codec_id
>= CODEC_ID_PCM_S16LE
) &&
784 (ac
->codec_id
< CODEC_ID_ADPCM_IMA_QT
) )
785 audio_profile
= PROFILE_AUDIO_PCM
;
787 DPRINTF(E_DEBUG
, L_METADATA
, "Unhandled audio codec [0x%X]\n", ac
->codec_id
);
790 asprintf(&m
.frequency
, "%u", ac
->sample_rate
);
791 #if LIBAVCODEC_VERSION_INT < (52<<16)
792 asprintf(&m
.bps
, "%u", ac
->bits_per_sample
);
794 asprintf(&m
.bps
, "%u", ac
->bits_per_coded_sample
);
796 asprintf(&m
.channels
, "%u", ac
->channels
);
801 int duration
, hours
, min
, sec
, ms
;
802 ts_timestamp_t ts_timestamp
= NONE
;
803 DPRINTF(E_DEBUG
, L_METADATA
, "Container: '%s' [%s]\n", ctx
->iformat
->name
, basename(path
));
804 asprintf(&m
.resolution
, "%dx%d", vc
->width
, vc
->height
);
805 if( ctx
->bit_rate
> 8 )
806 asprintf(&m
.bitrate
, "%u", ctx
->bit_rate
/ 8);
807 if( ctx
->duration
> 0 ) {
808 duration
= (int)(ctx
->duration
/ AV_TIME_BASE
);
809 hours
= (int)(duration
/ 3600);
810 min
= (int)(duration
/ 60 % 60);
811 sec
= (int)(duration
% 60);
812 ms
= (int)(ctx
->duration
/ (AV_TIME_BASE
/1000) % 1000);
813 asprintf(&m
.duration
, "%d:%02d:%02d.%03d", hours
, min
, sec
, ms
);
816 /* NOTE: The DLNA spec only provides for ASF (WMV), TS, PS, and MP4 containers.
817 * Skip DLNA parsing for everything else. */
818 if( strcmp(ctx
->iformat
->name
, "avi") == 0 )
820 asprintf(&m
.mime
, "video/x-msvideo");
821 if( vc
->codec_id
== CODEC_ID_MPEG4
)
823 fourcc
[0] = vc
->codec_tag
& 0xff;
824 fourcc
[1] = vc
->codec_tag
>>8 & 0xff;
825 fourcc
[2] = vc
->codec_tag
>>16 & 0xff;
826 fourcc
[3] = vc
->codec_tag
>>24 & 0xff;
827 if( memcmp(fourcc
, "XVID", 4) == 0 ||
828 memcmp(fourcc
, "DX50", 4) == 0 ||
829 memcmp(fourcc
, "DIVX", 4) == 0 )
830 asprintf(&m
.creator
, "DiVX");
833 else if( strcmp(ctx
->iformat
->name
, "mov,mp4,m4a,3gp,3g2,mj2") == 0 &&
834 ends_with(path
, ".mov") )
835 asprintf(&m
.mime
, "video/quicktime");
836 else if( strncmp(ctx
->iformat
->name
, "matroska", 8) == 0 )
837 asprintf(&m
.mime
, "video/x-matroska");
838 else if( strcmp(ctx
->iformat
->name
, "flv") == 0 )
839 asprintf(&m
.mime
, "video/x-flv");
843 switch( vc
->codec_id
)
845 case CODEC_ID_MPEG1VIDEO
:
846 if( strcmp(ctx
->iformat
->name
, "mpeg") == 0 )
848 if( (vc
->width
== 352) &&
849 (vc
->height
<= 288) )
851 asprintf(&m
.dlna_pn
, "MPEG1;%s", dlna_no_conv
);
853 asprintf(&m
.mime
, "video/mpeg");
856 case CODEC_ID_MPEG2VIDEO
:
857 m
.dlna_pn
= malloc(64);
858 off
= sprintf(m
.dlna_pn
, "MPEG_");
859 if( strcmp(ctx
->iformat
->name
, "mpegts") == 0 )
861 DPRINTF(E_DEBUG
, L_METADATA
, "Stream %d of %s is %s MPEG2 TS\n",
862 video_stream
, basename(path
), m
.resolution
);
863 off
+= sprintf(m
.dlna_pn
+off
, "TS_");
864 if( (vc
->width
>= 1280) &&
865 (vc
->height
>= 720) )
867 off
+= sprintf(m
.dlna_pn
+off
, "HD_NA");
871 off
+= sprintf(m
.dlna_pn
+off
, "SD_");
872 if( (vc
->height
== 576) ||
873 (vc
->height
== 288) )
874 off
+= sprintf(m
.dlna_pn
+off
, "EU");
876 off
+= sprintf(m
.dlna_pn
+off
, "NA");
879 if( ts
->packet_size
== MPEG_TS_PACKET_LENGTH_DLNA
)
881 if( dlna_timestamp_is_present(path
) )
882 ts_timestamp
= VALID
;
884 ts_timestamp
= EMPTY
;
886 else if( ts
->packet_size
!= MPEG_TS_PACKET_LENGTH
)
888 DPRINTF(E_DEBUG
, L_METADATA
, "Unsupported DLNA TS packet size [%d] (%s)\n",
889 ts
->packet_size
, basename(path
));
893 switch( ts_timestamp
)
896 asprintf(&m
.mime
, "video/mpeg");
898 off
+= sprintf(m
.dlna_pn
+off
, "_ISO");
901 off
+= sprintf(m
.dlna_pn
+off
, "_T");
903 asprintf(&m
.mime
, "video/vnd.dlna.mpeg-tts");
908 else if( strcmp(ctx
->iformat
->name
, "mpeg") == 0 )
910 DPRINTF(E_DEBUG
, L_METADATA
, "Stream %d of %s is %s MPEG2 PS\n",
911 video_stream
, basename(path
), m
.resolution
);
912 off
+= sprintf(m
.dlna_pn
+off
, "PS_");
913 if( (vc
->height
== 576) ||
914 (vc
->height
== 288) )
915 off
+= sprintf(m
.dlna_pn
+off
, "PAL");
917 off
+= sprintf(m
.dlna_pn
+off
, "NTSC");
918 asprintf(&m
.mime
, "video/mpeg");
922 DPRINTF(E_DEBUG
, L_METADATA
, "Stream %d of %s [%s] is %s non-DLNA MPEG2\n",
923 video_stream
, basename(path
), ctx
->iformat
->name
, m
.resolution
);
928 sprintf(m
.dlna_pn
+off
, ";%s", dlna_no_conv
);
931 m
.dlna_pn
= malloc(128);
932 off
= sprintf(m
.dlna_pn
, "AVC_");
934 if( strcmp(ctx
->iformat
->name
, "mpegts") == 0 )
936 off
+= sprintf(m
.dlna_pn
+off
, "TS_");
937 switch( vc
->profile
)
939 case FF_PROFILE_H264_BASELINE
:
940 off
+= sprintf(m
.dlna_pn
+off
, "BL_");
941 if( vc
->width
<= 352 &&
943 vc
->bit_rate
<= 384000 )
945 off
+= sprintf(m
.dlna_pn
+off
, "CIF15_");
948 else if( vc
->width
<= 352 &&
950 vc
->bit_rate
<= 3000000 )
952 off
+= sprintf(m
.dlna_pn
+off
, "CIF30_");
955 /* Fall back to Main Profile if it doesn't match a Baseline DLNA profile. */
959 case FF_PROFILE_H264_MAIN
:
960 off
+= sprintf(m
.dlna_pn
+off
, "MP_");
961 if( vc
->profile
!= FF_PROFILE_H264_BASELINE
&&
962 vc
->profile
!= FF_PROFILE_H264_MAIN
)
964 DPRINTF(E_DEBUG
, L_METADATA
, "Unknown AVC profile %d; assuming MP. [%s]\n",
965 vc
->profile
, basename(path
));
967 if( vc
->width
<= 720 &&
969 vc
->bit_rate
<= 10000000 )
971 off
+= sprintf(m
.dlna_pn
+off
, "SD_");
973 else if( vc
->width
<= 1920 &&
974 vc
->height
<= 1152 &&
975 vc
->bit_rate
<= 20000000 )
977 off
+= sprintf(m
.dlna_pn
+off
, "HD_");
981 DPRINTF(E_DEBUG
, L_METADATA
, "Unsupported h.264 video profile! [%s, %dx%d, %dbps : %s]\n",
982 m
.dlna_pn
, vc
->width
, vc
->height
, vc
->bit_rate
, basename(path
));
987 case FF_PROFILE_H264_HIGH
:
988 off
+= sprintf(m
.dlna_pn
+off
, "HP_");
989 if( vc
->width
<= 1920 &&
990 vc
->height
<= 1152 &&
991 vc
->bit_rate
<= 30000000 &&
992 audio_profile
== PROFILE_AUDIO_AC3
)
994 off
+= sprintf(m
.dlna_pn
+off
, "HD_");
998 DPRINTF(E_DEBUG
, L_METADATA
, "Unsupported h.264 HP video profile! [%dbps, %d audio : %s]\n",
999 vc
->bit_rate
, audio_profile
, basename(path
));
1007 switch( audio_profile
)
1009 case PROFILE_AUDIO_MP3
:
1010 off
+= sprintf(m
.dlna_pn
+off
, "MPEG1_L3");
1012 case PROFILE_AUDIO_AC3
:
1013 off
+= sprintf(m
.dlna_pn
+off
, "AC3");
1015 case PROFILE_AUDIO_AAC
:
1016 case PROFILE_AUDIO_AAC_MULT5
:
1017 off
+= sprintf(m
.dlna_pn
+off
, "AAC_MULT5");
1020 DPRINTF(E_DEBUG
, L_METADATA
, "No DLNA profile found for %s file [%s]\n",
1021 m
.dlna_pn
, basename(path
));
1028 ts
= ctx
->priv_data
;
1029 if( ts
->packet_size
== MPEG_TS_PACKET_LENGTH_DLNA
)
1031 if( vc
->profile
== FF_PROFILE_H264_HIGH
||
1032 dlna_timestamp_is_present(path
) )
1033 ts_timestamp
= VALID
;
1035 ts_timestamp
= EMPTY
;
1037 else if( ts
->packet_size
!= MPEG_TS_PACKET_LENGTH
)
1039 DPRINTF(E_DEBUG
, L_METADATA
, "Unsupported DLNA TS packet size [%d] (%s)\n",
1040 ts
->packet_size
, basename(path
));
1044 switch( ts_timestamp
)
1048 off
+= sprintf(m
.dlna_pn
+off
, "_ISO");
1051 off
+= sprintf(m
.dlna_pn
+off
, "_T");
1053 asprintf(&m
.mime
, "video/vnd.dlna.mpeg-tts");
1058 else if( strcmp(ctx
->iformat
->name
, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
1060 off
+= sprintf(m
.dlna_pn
+off
, "MP4_");
1062 switch( vc
->profile
) {
1063 case FF_PROFILE_H264_BASELINE
:
1064 if( vc
->width
<= 352 &&
1067 if( ctx
->bit_rate
< 600000 )
1068 off
+= sprintf(m
.dlna_pn
+off
, "BL_CIF15_");
1069 else if( ctx
->bit_rate
< 5000000 )
1070 off
+= sprintf(m
.dlna_pn
+off
, "BL_CIF30_");
1072 goto mp4_mp_fallback
;
1074 if( audio_profile
== PROFILE_AUDIO_AMR
)
1076 off
+= sprintf(m
.dlna_pn
+off
, "AMR");
1078 else if( audio_profile
== PROFILE_AUDIO_AAC
)
1080 off
+= sprintf(m
.dlna_pn
+off
, "AAC_");
1081 if( ctx
->bit_rate
< 520000 )
1083 off
+= sprintf(m
.dlna_pn
+off
, "520");
1085 else if( ctx
->bit_rate
< 940000 )
1087 off
+= sprintf(m
.dlna_pn
+off
, "940");
1092 goto mp4_mp_fallback
;
1098 goto mp4_mp_fallback
;
1101 else if( vc
->width
<= 720 &&
1104 if( vc
->level
== 30 &&
1105 audio_profile
== PROFILE_AUDIO_AAC
&&
1106 ctx
->bit_rate
<= 5000000 )
1107 off
+= sprintf(m
.dlna_pn
+off
, "BL_L3L_SD_AAC");
1108 else if( vc
->level
<= 31 &&
1109 audio_profile
== PROFILE_AUDIO_AAC
&&
1110 ctx
->bit_rate
<= 15000000 )
1111 off
+= sprintf(m
.dlna_pn
+off
, "BL_L31_HD_AAC");
1113 goto mp4_mp_fallback
;
1115 else if( vc
->width
<= 1280 &&
1118 if( vc
->level
<= 31 &&
1119 audio_profile
== PROFILE_AUDIO_AAC
&&
1120 ctx
->bit_rate
<= 15000000 )
1121 off
+= sprintf(m
.dlna_pn
+off
, "BL_L31_HD_AAC");
1122 else if( vc
->level
<= 32 &&
1123 audio_profile
== PROFILE_AUDIO_AAC
&&
1124 ctx
->bit_rate
<= 21000000 )
1125 off
+= sprintf(m
.dlna_pn
+off
, "BL_L32_HD_AAC");
1127 goto mp4_mp_fallback
;
1130 goto mp4_mp_fallback
;
1132 case FF_PROFILE_H264_MAIN
:
1134 off
+= sprintf(m
.dlna_pn
+off
, "MP_");
1135 /* AVC MP4 SD profiles - 10 Mbps max */
1136 if( vc
->width
<= 720 &&
1137 vc
->height
<= 576 &&
1138 vc
->bit_rate
<= 10000000 )
1140 sprintf(m
.dlna_pn
+off
, "SD_");
1141 if( audio_profile
== PROFILE_AUDIO_AC3
)
1142 off
+= sprintf(m
.dlna_pn
+off
, "AC3");
1143 else if( audio_profile
== PROFILE_AUDIO_AAC
||
1144 audio_profile
== PROFILE_AUDIO_AAC_MULT5
)
1145 off
+= sprintf(m
.dlna_pn
+off
, "AAC_MULT5");
1146 else if( audio_profile
== PROFILE_AUDIO_MP3
)
1147 off
+= sprintf(m
.dlna_pn
+off
, "MPEG1_L3");
1149 m
.dlna_pn
[10] = '\0';
1151 else if( vc
->width
<= 1280 &&
1152 vc
->height
<= 720 &&
1153 vc
->bit_rate
<= 15000000 &&
1154 audio_profile
== PROFILE_AUDIO_AAC
)
1156 off
+= sprintf(m
.dlna_pn
+off
, "HD_720p_AAC");
1158 else if( vc
->width
<= 1920 &&
1159 vc
->height
<= 1080 &&
1160 vc
->bit_rate
<= 21000000 &&
1161 audio_profile
== PROFILE_AUDIO_AAC
)
1163 off
+= sprintf(m
.dlna_pn
+off
, "HD_1080i_AAC");
1165 if( strlen(m
.dlna_pn
) <= 11 )
1167 DPRINTF(E_DEBUG
, L_METADATA
, "No DLNA profile found for %s file %s\n",
1168 m
.dlna_pn
, basename(path
));
1173 case FF_PROFILE_H264_HIGH
:
1174 if( vc
->width
<= 1920 &&
1175 vc
->height
<= 1080 &&
1176 vc
->bit_rate
<= 25000000 &&
1177 audio_profile
== PROFILE_AUDIO_AAC
)
1179 off
+= sprintf(m
.dlna_pn
+off
, "HP_HD_AAC");
1183 DPRINTF(E_DEBUG
, L_METADATA
, "AVC profile [%d] not recognized for file %s\n",
1184 vc
->profile
, basename(path
));
1196 sprintf(m
.dlna_pn
+off
, ";%s", dlna_no_conv
);
1197 DPRINTF(E_DEBUG
, L_METADATA
, "Stream %d of %s is h.264\n", video_stream
, basename(path
));
1199 case CODEC_ID_MPEG4
:
1200 fourcc
[0] = vc
->codec_tag
& 0xff;
1201 fourcc
[1] = vc
->codec_tag
>>8 & 0xff;
1202 fourcc
[2] = vc
->codec_tag
>>16 & 0xff;
1203 fourcc
[3] = vc
->codec_tag
>>24 & 0xff;
1204 DPRINTF(E_DEBUG
, L_METADATA
, "Stream %d of %s is MPEG4 [%c%c%c%c/0x%X]\n",
1205 video_stream
, basename(path
),
1206 isprint(fourcc
[0]) ? fourcc
[0] : '_',
1207 isprint(fourcc
[1]) ? fourcc
[1] : '_',
1208 isprint(fourcc
[2]) ? fourcc
[2] : '_',
1209 isprint(fourcc
[3]) ? fourcc
[3] : '_',
1212 if( strcmp(ctx
->iformat
->name
, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
1214 m
.dlna_pn
= malloc(128);
1215 off
= sprintf(m
.dlna_pn
, "MPEG4_P2_");
1217 if( ends_with(path
, ".3gp") )
1219 asprintf(&m
.mime
, "video/3gpp");
1220 switch( audio_profile
)
1222 case PROFILE_AUDIO_AAC
:
1223 off
+= sprintf(m
.dlna_pn
+off
, "3GPP_SP_L0B_AAC");
1225 case PROFILE_AUDIO_AMR
:
1226 off
+= sprintf(m
.dlna_pn
+off
, "3GPP_SP_L0B_AMR");
1229 DPRINTF(E_DEBUG
, L_METADATA
, "No DLNA profile found for MPEG4-P2 3GP/0x%X file %s\n",
1230 ac
->codec_id
, basename(path
));
1238 if( ctx
->bit_rate
<= 1000000 &&
1239 audio_profile
== PROFILE_AUDIO_AAC
)
1241 off
+= sprintf(m
.dlna_pn
+off
, "MP4_ASP_AAC");
1243 else if( ctx
->bit_rate
<= 4000000 &&
1245 vc
->height
<= 480 &&
1246 audio_profile
== PROFILE_AUDIO_AAC
)
1248 off
+= sprintf(m
.dlna_pn
+off
, "MP4_SP_VGA_AAC");
1252 DPRINTF(E_DEBUG
, L_METADATA
, "Unsupported h.264 video profile! [%dx%d, %dbps]\n",
1261 sprintf(m
.dlna_pn
+off
, ";%s", dlna_no_conv
);
1265 /* I'm not 100% sure this is correct, but it works on everything I could get my hands on */
1266 if( vc
->extradata_size
> 0 )
1268 if( !((vc
->extradata
[0] >> 3) & 1) )
1270 if( !((vc
->extradata
[0] >> 6) & 1) )
1274 if( strcmp(ctx
->iformat
->name
, "asf") != 0 )
1276 DPRINTF(E_DEBUG
, L_METADATA
, "Skipping DLNA parsing for non-ASF VC1 file %s\n", path
);
1279 m
.dlna_pn
= malloc(64);
1280 off
= sprintf(m
.dlna_pn
, "WMV");
1281 DPRINTF(E_DEBUG
, L_METADATA
, "Stream %d of %s is VC1\n", video_stream
, basename(path
));
1282 asprintf(&m
.mime
, "video/x-ms-wmv");
1283 if( (vc
->width
<= 176) &&
1284 (vc
->height
<= 144) &&
1287 off
+= sprintf(m
.dlna_pn
+off
, "SPLL_");
1288 switch( audio_profile
)
1290 case PROFILE_AUDIO_MP3
:
1291 off
+= sprintf(m
.dlna_pn
+off
, "MP3");
1293 case PROFILE_AUDIO_WMA_BASE
:
1294 off
+= sprintf(m
.dlna_pn
+off
, "BASE");
1297 DPRINTF(E_DEBUG
, L_METADATA
, "No DLNA profile found for WMVSPLL/0x%X file %s\n",
1298 audio_profile
, basename(path
));
1304 else if( (vc
->width
<= 352) &&
1305 (vc
->height
<= 288) &&
1306 (vc
->profile
== 0) &&
1307 (ctx
->bit_rate
/8 <= 384000) )
1309 off
+= sprintf(m
.dlna_pn
+off
, "SPML_");
1310 switch( audio_profile
)
1312 case PROFILE_AUDIO_MP3
:
1313 off
+= sprintf(m
.dlna_pn
+off
, "MP3");
1315 case PROFILE_AUDIO_WMA_BASE
:
1316 off
+= sprintf(m
.dlna_pn
+off
, "BASE");
1319 DPRINTF(E_DEBUG
, L_METADATA
, "No DLNA profile found for WMVSPML/0x%X file %s\n",
1320 audio_profile
, basename(path
));
1326 else if( (vc
->width
<= 720) &&
1327 (vc
->height
<= 576) &&
1328 (ctx
->bit_rate
/8 <= 10000000) )
1330 off
+= sprintf(m
.dlna_pn
+off
, "MED_");
1331 switch( audio_profile
)
1333 case PROFILE_AUDIO_WMA_PRO
:
1334 off
+= sprintf(m
.dlna_pn
+off
, "PRO");
1336 case PROFILE_AUDIO_WMA_FULL
:
1337 off
+= sprintf(m
.dlna_pn
+off
, "FULL");
1339 case PROFILE_AUDIO_WMA_BASE
:
1340 off
+= sprintf(m
.dlna_pn
+off
, "BASE");
1343 DPRINTF(E_DEBUG
, L_METADATA
, "No DLNA profile found for WMVMED/0x%X file %s\n",
1344 audio_profile
, basename(path
));
1350 else if( (vc
->width
<= 1920) &&
1351 (vc
->height
<= 1080) &&
1352 (ctx
->bit_rate
/8 <= 20000000) )
1354 off
+= sprintf(m
.dlna_pn
+off
, "HIGH_");
1355 switch( audio_profile
)
1357 case PROFILE_AUDIO_WMA_PRO
:
1358 off
+= sprintf(m
.dlna_pn
+off
, "PRO");
1360 case PROFILE_AUDIO_WMA_FULL
:
1361 off
+= sprintf(m
.dlna_pn
+off
, "FULL");
1364 DPRINTF(E_DEBUG
, L_METADATA
, "No DLNA profile found for WMVHIGH/0x%X file %s\n",
1365 audio_profile
, basename(path
));
1372 sprintf(m
.dlna_pn
+off
, ";%s", dlna_no_conv
);
1374 case CODEC_ID_MSMPEG4V3
:
1375 asprintf(&m
.mime
, "video/x-msvideo");
1377 DPRINTF(E_DEBUG
, L_METADATA
, "Stream %d of %s is %s [type %d]\n",
1378 video_stream
, basename(path
), m
.resolution
, vc
->codec_id
);
1384 if( strcmp(ctx
->iformat
->name
, "avi") == 0 )
1385 asprintf(&m
.mime
, "video/x-msvideo");
1386 else if( strncmp(ctx
->iformat
->name
, "mpeg", 4) == 0 )
1387 asprintf(&m
.mime
, "video/mpeg");
1388 else if( strcmp(ctx
->iformat
->name
, "asf") == 0 )
1389 asprintf(&m
.mime
, "video/x-ms-wmv");
1390 else if( strcmp(ctx
->iformat
->name
, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
1391 if( ends_with(path
, ".mov") )
1392 asprintf(&m
.mime
, "video/quicktime");
1394 asprintf(&m
.mime
, "video/mp4");
1395 else if( strncmp(ctx
->iformat
->name
, "matroska", 8) == 0 )
1396 asprintf(&m
.mime
, "video/x-matroska");
1397 else if( strcmp(ctx
->iformat
->name
, "flv") == 0 )
1398 asprintf(&m
.mime
, "video/x-flv");
1400 DPRINTF(E_WARN
, L_METADATA
, "%s: Unhandled format: %s\n", path
, ctx
->iformat
->name
);
1403 if( strcmp(ctx
->iformat
->name
, "asf") == 0 )
1405 if( readtags((char *)path
, &video
, &file
, "en_US", "asf") == 0 )
1407 if( video
.title
&& *video
.title
)
1409 m
.title
= escape_tag(trim(video
.title
), 1);
1411 if( video
.genre
&& *video
.genre
)
1413 m
.genre
= escape_tag(trim(video
.genre
), 1);
1415 if( video
.contributor
[ROLE_TRACKARTIST
] && *video
.contributor
[ROLE_TRACKARTIST
] )
1417 m
.artist
= escape_tag(trim(video
.contributor
[ROLE_TRACKARTIST
]), 1);
1419 if( video
.contributor
[ROLE_ALBUMARTIST
] && *video
.contributor
[ROLE_ALBUMARTIST
] )
1421 m
.creator
= escape_tag(trim(video
.contributor
[ROLE_ALBUMARTIST
]), 1);
1425 m
.creator
= m
.artist
;
1426 free_flags
&= ~FLAG_CREATOR
;
1431 #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
1432 else if( strcmp(ctx
->iformat
->name
, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
1436 AVMetadataTag
*tag
= NULL
;
1438 //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Metadata:\n");
1439 while( (tag
= av_metadata_get(ctx
->metadata
, "", tag
, AV_METADATA_IGNORE_SUFFIX
)) )
1441 //DEBUG DPRINTF(E_DEBUG, L_METADATA, " %-16s: %s\n", tag->key, tag->value);
1442 if( strcmp(tag
->key
, "title") == 0 )
1443 m
.title
= escape_tag(trim(tag
->value
), 1);
1444 else if( strcmp(tag
->key
, "genre") == 0 )
1445 m
.genre
= escape_tag(trim(tag
->value
), 1);
1446 else if( strcmp(tag
->key
, "artist") == 0 )
1447 m
.artist
= escape_tag(trim(tag
->value
), 1);
1448 else if( strcmp(tag
->key
, "comment") == 0 )
1449 m
.comment
= escape_tag(trim(tag
->value
), 1);
1456 av_close_input_file(ctx
);
1459 if( ends_with(path
, ".TiVo") && is_tivo_file(path
) )
1466 m
.mime
= realloc(m
.mime
, 18);
1467 strcpy(m
.mime
, "video/x-tivo-mpeg");
1471 m
.title
= strdup(name
);
1473 album_art
= find_album_art(path
, video
.image
, video
.image_size
);
1476 ret
= sql_exec(db
, "INSERT into DETAILS"
1477 " (PATH, SIZE, TIMESTAMP, DURATION, DATE, CHANNELS, BITRATE, SAMPLERATE, RESOLUTION,"
1478 " TITLE, CREATOR, ARTIST, GENRE, COMMENT, DLNA_PN, MIME, ALBUM_ART) "
1480 " (%Q, %lld, %ld, %Q, %Q, %Q, %Q, %Q, %Q, '%q', %Q, %Q, %Q, %Q, %Q, '%q', %lld);",
1481 path
, file
.st_size
, file
.st_mtime
, m
.duration
,
1482 m
.date
, m
.channels
, m
.bitrate
, m
.frequency
, m
.resolution
,
1483 m
.title
, m
.creator
, m
.artist
, m
.genre
, m
.comment
, m
.dlna_pn
,
1485 if( ret
!= SQLITE_OK
)
1487 fprintf(stderr
, "Error inserting details for '%s'!\n", path
);
1492 ret
= sqlite3_last_insert_rowid(db
);
1493 check_for_captions(path
, ret
);
1495 free_metadata(&m
, free_flags
);