void DefaultReader::readHeader() { av_metadata_conv( this->pFormatContext_.get(), NULL, this->pFormatContext_->iformat->metadata_conv ); AVMetadataTag * mt = NULL; if( ( mt = av_metadata_get( this->pFormatContext_->metadata, "title", NULL, 0 ) ) ) { this->setTitle( mt->value ); } if( ( mt = av_metadata_get( this->pFormatContext_->metadata, "author", NULL, 0 ) ) ) { this->setArtist( mt->value ); } if( ( mt = av_metadata_get( this->pFormatContext_->metadata, "copyright", NULL, 0 ) ) ) { this->setCopyright( mt->value ); } if( ( mt = av_metadata_get( this->pFormatContext_->metadata, "comment", NULL, 0 ) ) ) { this->setComment( mt->value ); } if( ( mt = av_metadata_get( this->pFormatContext_->metadata, "album", NULL, 0 ) ) ) { this->setAlbum( mt->value ); } if( ( mt = av_metadata_get( this->pFormatContext_->metadata, "year", NULL, 0 ) ) ) { this->setYear( std::atoi( mt->value ) ); } if( ( mt = av_metadata_get( this->pFormatContext_->metadata, "track", NULL, 0 ) ) ) { this->setIndex( std::atoi( mt->value ) ); } if( ( mt = av_metadata_get( this->pFormatContext_->metadata, "genre", NULL, 0 ) ) ) { this->setGenre( mt->value ); } }
static void show_format(AVFormatContext *fmt_ctx) { AVMetadataTag *tag = NULL; char val_str[128]; printf("[FORMAT]\n"); printf("filename=%s\n", fmt_ctx->filename); printf("nb_streams=%d\n", fmt_ctx->nb_streams); printf("format_name=%s\n", fmt_ctx->iformat->name); printf("format_long_name=%s\n", fmt_ctx->iformat->long_name); printf("start_time=%s\n", time_value_string(val_str, sizeof(val_str), fmt_ctx->start_time, &AV_TIME_BASE_Q)); printf("duration=%s\n", time_value_string(val_str, sizeof(val_str), fmt_ctx->duration, &AV_TIME_BASE_Q)); printf("size=%s\n", value_string(val_str, sizeof(val_str), fmt_ctx->file_size, unit_byte_str)); printf("bit_rate=%s\n", value_string(val_str, sizeof(val_str), fmt_ctx->bit_rate, unit_bit_per_second_str)); if (convert_tags) av_metadata_conv(fmt_ctx, NULL, fmt_ctx->iformat->metadata_conv); while ((tag = av_metadata_get(fmt_ctx->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX))) printf("TAG:%s=%s\n", tag->key, tag->value); printf("[/FORMAT]\n"); }
void File::initializeMediaProperties() { #ifdef HAVE_AVFORMAT av_register_all(); AVFormatContext* ctx; if ((av_open_input_file(&ctx, getPath(), NULL, 0, NULL) == 0) && (av_find_stream_info(ctx) >= 0)) { // duration if (ctx->duration != AV_NOPTS_VALUE) duration = strdup(Utils::timeToString(ctx->duration / AV_TIME_BASE).c_str()); // bitrate if (ctx->bit_rate > 0) bitrate = ctx->bit_rate / 8; for (unsigned int i = 0; i < ctx->nb_streams; i++) { // samplerate if(samplerate <= 0) samplerate = ctx->streams[i]->codec->sample_rate; // channels if(channels <= 0) channels = ctx->streams[i]->codec->channels; // width if(width <= 0) width = ctx->streams[i]->codec->width; // height if(height <= 0) height = ctx->streams[i]->codec->height; if ((samplerate > 0) && (channels > 0) && (width > 0) && (height > 0)) i = ctx->nb_streams; } #if LIBAVFORMAT_VERSION_INT < (53<<16) // title if(ctx->title != NULL) title = strdup(ctx->title); // artist if(ctx->author != NULL) author = strdup(ctx->author); // album if(ctx->album != NULL) album = strdup(ctx->album); // genre if(ctx->genre != NULL) genre = strdup(ctx->genre); // description / comment if(ctx->comment != NULL) comment = strdup(ctx->comment); // track number if(ctx->track > 0) track = ctx->track; // date / year if(ctx->year > 0) year = ctx->year; #else av_metadata_conv(ctx, NULL, ctx->iformat->metadata_conv); AVMetadataTag *mtitle, *mauthor, *malbum, *mgenre, *mcomment, *mtrack, *myear; mtitle = av_metadata_get(ctx->metadata, "title", NULL, 0); mauthor = av_metadata_get(ctx->metadata, "author", NULL, 0); malbum = av_metadata_get(ctx->metadata, "album", NULL, 0); mgenre = av_metadata_get(ctx->metadata, "genre", NULL, 0); mcomment = av_metadata_get(ctx->metadata, "comment", NULL, 0); mtrack = av_metadata_get(ctx->metadata, "track", NULL, 0); myear = av_metadata_get(ctx->metadata, "year", NULL, 0); // title if(mtitle != NULL) title = strdup(mtitle->value); // artist if(mauthor != NULL) author = strdup(mauthor->value); // album if(malbum != NULL) album = strdup(malbum->value); // genre if(mgenre != NULL) genre = strdup(mgenre->value); // description / comment if(mcomment != NULL) comment = strdup(mcomment->value); // track number if(mtrack != NULL) track = Utils::stringToInteger(mtrack->value); // date / year if(myear != NULL) year = Utils::stringToInteger(myear->value); #endif //LIBAVFORMAT_VERSION_INT } av_close_input_file(ctx); #endif //HAVE_AVFORMAT }
int scan_metadata_ffmpeg(char *file, struct media_file_info *mfi) { AVFormatContext *ctx; const struct metadata_map *extra_md_map; enum CodecID codec_id; enum CodecID video_codec_id; enum CodecID audio_codec_id; AVStream *video_stream; AVStream *audio_stream; int mdcount; int i; int ret; ctx = NULL; #if LIBAVFORMAT_VERSION_MAJOR >= 53 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR >= 3) ret = avformat_open_input(&ctx, file, NULL, NULL); #else ret = av_open_input_file(&ctx, file, NULL, 0, NULL); #endif if (ret != 0) { DPRINTF(E_WARN, L_SCAN, "Cannot open media file '%s': %s\n", file, strerror(AVUNERROR(ret))); return -1; } ret = av_find_stream_info(ctx); if (ret < 0) { DPRINTF(E_WARN, L_SCAN, "Cannot get stream info: %s\n", strerror(AVUNERROR(ret))); av_close_input_file(ctx); return -1; } #if 0 /* Dump input format as determined by ffmpeg */ # if LIBAVFORMAT_VERSION_MAJOR >= 52 || (LIBAVFORMAT_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 101) av_dump_format(ctx, 0, file, 0); # else dump_format(ctx, 0, file, FALSE); # endif #endif DPRINTF(E_DBG, L_SCAN, "File has %d streams\n", ctx->nb_streams); /* Extract codec IDs, check for video */ video_codec_id = CODEC_ID_NONE; video_stream = NULL; audio_codec_id = CODEC_ID_NONE; audio_stream = NULL; for (i = 0; i < ctx->nb_streams; i++) { switch (ctx->streams[i]->codec->codec_type) { #if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64) case AVMEDIA_TYPE_VIDEO: #else case CODEC_TYPE_VIDEO: #endif if (!video_stream) { DPRINTF(E_DBG, L_SCAN, "File has video (stream %d)\n", i); mfi->has_video = 1; video_stream = ctx->streams[i]; video_codec_id = video_stream->codec->codec_id; } break; #if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64) case AVMEDIA_TYPE_AUDIO: #else case CODEC_TYPE_AUDIO: #endif if (!audio_stream) { audio_stream = ctx->streams[i]; audio_codec_id = audio_stream->codec->codec_id; } break; default: break; } } if (audio_codec_id == CODEC_ID_NONE) { DPRINTF(E_DBG, L_SCAN, "File has no audio streams, discarding\n"); av_close_input_file(ctx); return -1; } /* Common media information */ if (ctx->duration > 0) mfi->song_length = ctx->duration / (AV_TIME_BASE / 1000); /* ms */ if (ctx->bit_rate > 0) mfi->bitrate = ctx->bit_rate / 1000; else if (ctx->duration > AV_TIME_BASE) /* guesstimate */ mfi->bitrate = ((mfi->file_size * 8) / (ctx->duration / AV_TIME_BASE)) / 1000; DPRINTF(E_DBG, L_SCAN, "Duration %d ms, bitrate %d kbps\n", mfi->song_length, mfi->bitrate); /* Get some more information on the audio stream */ if (audio_stream) { if (audio_stream->codec->sample_rate != 0) mfi->samplerate = audio_stream->codec->sample_rate; /* Try sample format first */ #if LIBAVUTIL_VERSION_MAJOR >= 51 || (LIBAVUTIL_VERSION_MAJOR == 51 && LIBAVUTIL_VERSION_MINOR >= 4) mfi->bits_per_sample = 8 * av_get_bytes_per_sample(audio_stream->codec->sample_fmt); #elif LIBAVCODEC_VERSION_MAJOR >= 53 mfi->bits_per_sample = av_get_bits_per_sample_fmt(audio_stream->codec->sample_fmt); #else mfi->bits_per_sample = av_get_bits_per_sample_format(audio_stream->codec->sample_fmt); #endif if (mfi->bits_per_sample == 0) { /* Try codec */ mfi->bits_per_sample = av_get_bits_per_sample(audio_codec_id); } DPRINTF(E_DBG, L_SCAN, "samplerate %d, bps %d\n", mfi->samplerate, mfi->bits_per_sample); } /* Check codec */ extra_md_map = NULL; codec_id = (mfi->has_video) ? video_codec_id : audio_codec_id; switch (codec_id) { case CODEC_ID_AAC: DPRINTF(E_DBG, L_SCAN, "AAC\n"); mfi->type = strdup("m4a"); mfi->codectype = strdup("mp4a"); mfi->description = strdup("AAC audio file"); break; case CODEC_ID_ALAC: DPRINTF(E_DBG, L_SCAN, "ALAC\n"); mfi->type = strdup("m4a"); mfi->codectype = strdup("alac"); mfi->description = strdup("AAC audio file"); break; case CODEC_ID_FLAC: DPRINTF(E_DBG, L_SCAN, "FLAC\n"); mfi->type = strdup("flac"); mfi->codectype = strdup("flac"); mfi->description = strdup("FLAC audio file"); extra_md_map = md_map_vorbis; break; case CODEC_ID_MUSEPACK7: case CODEC_ID_MUSEPACK8: DPRINTF(E_DBG, L_SCAN, "Musepack\n"); mfi->type = strdup("mpc"); mfi->codectype = strdup("mpc"); mfi->description = strdup("Musepack audio file"); break; case CODEC_ID_MPEG4: /* Video */ case CODEC_ID_H264: DPRINTF(E_DBG, L_SCAN, "MPEG4 video\n"); mfi->type = strdup("m4v"); mfi->codectype = strdup("mp4v"); mfi->description = strdup("MPEG-4 video file"); extra_md_map = md_map_tv; break; case CODEC_ID_MP3: DPRINTF(E_DBG, L_SCAN, "MP3\n"); mfi->type = strdup("mp3"); mfi->codectype = strdup("mpeg"); mfi->description = strdup("MPEG audio file"); extra_md_map = md_map_id3; break; case CODEC_ID_VORBIS: DPRINTF(E_DBG, L_SCAN, "VORBIS\n"); mfi->type = strdup("ogg"); mfi->codectype = strdup("ogg"); mfi->description = strdup("Ogg Vorbis audio file"); extra_md_map = md_map_vorbis; break; case CODEC_ID_WMAVOICE: DPRINTF(E_DBG, L_SCAN, "WMA Voice\n"); mfi->type = strdup("wma"); mfi->codectype = strdup("wmav"); mfi->description = strdup("WMA audio file"); break; case CODEC_ID_WMAPRO: DPRINTF(E_DBG, L_SCAN, "WMA Pro\n"); mfi->type = strdup("wmap"); mfi->codectype = strdup("wma"); mfi->description = strdup("WMA audio file"); break; case CODEC_ID_WMALOSSLESS: DPRINTF(E_DBG, L_SCAN, "WMA Lossless\n"); mfi->type = strdup("wma"); mfi->codectype = strdup("wmal"); mfi->description = strdup("WMA audio file"); break; case CODEC_ID_WMAV1: case CODEC_ID_WMAV2: DPRINTF(E_DBG, L_SCAN, "WMA V1/V2\n"); mfi->type = strdup("wma"); mfi->codectype = strdup("wma"); mfi->description = strdup("WMA audio file"); break; case CODEC_ID_PCM_S16LE ... CODEC_ID_PCM_F64LE: if (strcmp(ctx->iformat->name, "aiff") == 0) { DPRINTF(E_DBG, L_SCAN, "AIFF\n"); mfi->type = strdup("aif"); mfi->codectype = strdup("aif"); mfi->description = strdup("AIFF audio file"); break; } else if (strcmp(ctx->iformat->name, "wav") == 0) { DPRINTF(E_DBG, L_SCAN, "WAV\n"); mfi->type = strdup("wav"); mfi->codectype = strdup("wav"); mfi->description = strdup("WAV audio file"); break; } /* WARNING: will fallthrough to default case, don't move */ /* FALLTHROUGH */ default: DPRINTF(E_DBG, L_SCAN, "Unknown codec 0x%x (video: %s), format %s (%s)\n", codec_id, (mfi->has_video) ? "yes" : "no", ctx->iformat->name, ctx->iformat->long_name); mfi->type = strdup("unkn"); mfi->codectype = strdup("unkn"); if (mfi->has_video) { mfi->description = strdup("Unknown video file format"); extra_md_map = md_map_tv; } else mfi->description = strdup("Unknown audio file format"); break; } mdcount = 0; if ((!ctx->metadata) && (!audio_stream->metadata) && (video_stream && !video_stream->metadata)) { DPRINTF(E_WARN, L_SCAN, "ffmpeg reports no metadata\n"); goto skip_extract; } if (extra_md_map) { ret = extract_metadata(mfi, ctx, audio_stream, video_stream, extra_md_map); mdcount += ret; DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with extra md_map\n", ret); } #if LIBAVFORMAT_VERSION_MAJOR < 53 av_metadata_conv(ctx, NULL, ctx->iformat->metadata_conv); #endif ret = extract_metadata(mfi, ctx, audio_stream, video_stream, md_map_generic); mdcount += ret; DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with generic md_map, %d tags total\n", ret, mdcount); /* fix up TV metadata */ if (mfi->media_kind == 10) { /* I have no idea why this is, but iTunes reports a media kind of 64 for stik==10 (?!) */ mfi->media_kind = 64; } /* Unspecified video files are "Movies", media_kind 2 */ else if (mfi->has_video == 1) { mfi->media_kind = 2; } skip_extract: if (mdcount == 0) { /* ffmpeg doesn't support FLAC nor Musepack metadata, * and is buggy for some WMA variants, so fall back to the * legacy format-specific parsers until it gets fixed */ if ((codec_id == CODEC_ID_WMAPRO) || (codec_id == CODEC_ID_WMAVOICE) || (codec_id == CODEC_ID_WMALOSSLESS)) { DPRINTF(E_WARN, L_SCAN, "Falling back to legacy WMA scanner\n"); av_close_input_file(ctx); return (scan_get_wmainfo(file, mfi) ? 0 : -1); } #ifdef FLAC else if (codec_id == CODEC_ID_FLAC) { DPRINTF(E_WARN, L_SCAN, "Falling back to legacy FLAC scanner\n"); av_close_input_file(ctx); return (scan_get_flacinfo(file, mfi) ? 0 : -1); } #endif /* FLAC */ #ifdef MUSEPACK else if ((codec_id == CODEC_ID_MUSEPACK7) || (codec_id == CODEC_ID_MUSEPACK8)) { DPRINTF(E_WARN, L_SCAN, "Falling back to legacy Musepack scanner\n"); av_close_input_file(ctx); return (scan_get_mpcinfo(file, mfi) ? 0 : -1); } #endif /* MUSEPACK */ else DPRINTF(E_WARN, L_SCAN, "Could not extract any metadata\n"); } /* Just in case there's no title set ... */ if (mfi->title == NULL) mfi->title = strdup(mfi->fname); /* All done */ av_close_input_file(ctx); return 0; }
static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ AVFormatContext *avfc; AVFormatParameters ap; const AVOption *opt; AVMetadataTag *t = NULL; lavf_priv_t *priv= demuxer->priv; int i; //start_time = 0.0; char mp_filename[256]="mp:"; memset(&ap, 0, sizeof(AVFormatParameters)); //demux_lavf_find_geodata(demuxer); stream_seek(demuxer->stream, 0); int filepos=stream_tell(demuxer->stream); avfc = avformat_alloc_context(); if (opt_cryptokey) parse_cryptokey(avfc, opt_cryptokey); if (user_correct_pts != 0) avfc->flags |= AVFMT_FLAG_GENPTS; /* if (index_mode == 0) */ /* avfc->flags |= AVFMT_FLAG_IGNIDX; */ ap.prealloced_context = 1; #if 0 if(opt_probesize) { opt = av_set_int(avfc, "probesize", opt_probesize); if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option probesize to %u\n", opt_probesize); } if(opt_analyzeduration) { opt = av_set_int(avfc, "analyzeduration", opt_analyzeduration * AV_TIME_BASE); if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option analyzeduration to %u\n", opt_analyzeduration); } if(opt_avopt){ if(parse_avopts(avfc, opt_avopt) < 0){ mp_msg(MSGT_HEADER,MSGL_ERR, "Your options /%s/ look like gibberish to me pal\n", opt_avopt); return NULL; } } #endif if(demuxer->stream->url) { if (!strncmp(demuxer->stream->url, "ffmpeg://rtsp:", 14)) av_strlcpy(mp_filename, demuxer->stream->url + 9, sizeof(mp_filename)); else av_strlcat(mp_filename, demuxer->stream->url, sizeof(mp_filename)); } else av_strlcat(mp_filename, "foobar.dummy", sizeof(mp_filename)); priv->pb = av_alloc_put_byte(priv->buffer, BIO_BUFFER_SIZE, 0, demuxer, mp_read, NULL, mp_seek); priv->pb->read_seek = mp_read_seek; priv->pb->is_streamed = !demuxer->stream->end_pos || (demuxer->stream->flags & MP_STREAM_SEEK) != MP_STREAM_SEEK; filepos=stream_tell(demuxer->stream); if(av_open_input_stream(&avfc, priv->pb, mp_filename, priv->avif, &ap)<0){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_open_input_stream() failed\n"); return NULL; } filepos=stream_tell(demuxer->stream); priv->avfc= avfc; if(av_find_stream_info(avfc) < 0){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_find_stream_info() failed\n"); return NULL; } filepos=stream_tell(demuxer->stream); if(!strncmp(avfc->iformat->name,"aac",4)) get_aac_duration(demuxer,avfc); if(!strncmp(avfc->iformat->name,"mp3",4)) priv->avfc->duration = get_mp3_duration(demuxer) * AV_TIME_BASE; /* Add metadata. */ av_metadata_conv(avfc, NULL, avfc->iformat->metadata_conv); while((t = av_metadata_get(avfc->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))){ demux_info_add(demuxer, t->key, t->value); } for(i=0; i < avfc->nb_chapters; i++) { AVChapter *c = avfc->chapters[i]; uint64_t start = av_rescale_q(c->start, c->time_base, (AVRational){1,1000}); uint64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,1000}); t = av_metadata_get(c->metadata, "title", NULL, 0); demuxer_add_chapter(demuxer, t ? t->value : NULL, start, end); } demuxer->ttaflag = 0; for(i=0; i<avfc->nb_streams; i++) handle_stream(demuxer, avfc, i); if(demuxer->matroflag && !demuxer->ttaflag) return NULL; if(avfc->nb_programs) { int p; for (p = 0; p < avfc->nb_programs; p++) { AVProgram *program = avfc->programs[p]; t = av_metadata_get(program->metadata, "title", NULL, 0); mp_msg(MSGT_HEADER,MSGL_INFO,"LAVF: Program %d %s\n", program->id, t ? t->value : ""); } } mp_msg(MSGT_HEADER,MSGL_V,"LAVF: %d audio and %d video streams found\n",priv->audio_streams,priv->video_streams); mp_msg(MSGT_HEADER,MSGL_V,"LAVF: build %d\n", LIBAVFORMAT_BUILD); if(!priv->audio_streams) demuxer->audio->id=-2; // nosound // else if(best_audio > 0 && demuxer->audio->id == -1) demuxer->audio->id=best_audio; if(!priv->video_streams){ if(!priv->audio_streams){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF: no audio or video headers found - broken file?\n"); return NULL; } demuxer->video->id=-2; // audio-only } //else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video; filepos=stream_tell(demuxer->stream); int j=0; AVCodecContext *codec; AVCodec *avc; demuxer->audio_info = malloc(100*avfc->nb_streams); for(i=0; i<avfc->nb_streams; i++){ if(demuxer->a_streams[i]){ char *info = malloc(100); codec= ((AVStream *)avfc->streams[i])->codec; avc = avcodec_find_decoder(codec->codec_id); char *cn = avc ? avc->name : "unknown"; char *codec_name = malloc(100); strncpy(codec_name,cn,100); if((codec_name[0]=='d')&&(codec_name[1]=='c')&&(codec_name[2]=='a')) strncpy(codec_name,"dts",100); int a; for(a=0;codec_name[a];a++) if(codec_name[a]>='a'&&codec_name[a]<='z') codec_name[a]-=32; sprintf(info, "%s(%dHz %dCh)--%d", codec_name,codec->sample_rate, codec->channels, i); free(codec_name); memcpy(demuxer->audio_info+j*100,info, 100); j++; free(info); info = NULL; } } j = 0; demuxer->sub_info = malloc(100*avfc->nb_streams); for(i=0; i<avfc->nb_streams; i++){ if(demuxer->s_streams[i]){ char *info = malloc(100); AVStream *st= avfc->streams[i]; AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL, 0); codec= st->codec; if (lang && lang->value) strcpy(info, lang->value); else strcpy(info, "unknown"); sprintf(info, "%s--%d", info,i); memcpy(demuxer->sub_info+j*100,info, 100); j++; free(info); info = NULL; } } if(AV_NOPTS_VALUE == priv->avfc->start_time){ LOGW("priv->avfc->start_time = AV_NOPTS_VALUE"); demuxer->start_time = 0; }else{ demuxer->start_time = priv->avfc->start_time; } return demuxer; }