static mlt_properties find_default_streams( mlt_properties meta_media, AVFormatContext *context, int *audio_index, int *video_index ) { int i; char key[200]; mlt_properties_set_int( meta_media, "meta.media.nb_streams", context->nb_streams ); // Allow for multiple audio and video streams in the file and select first of each (if available) for( i = 0; i < context->nb_streams; i++ ) { // Get the codec context AVStream *stream = context->streams[ i ]; if ( ! stream ) continue; AVCodecContext *codec_context = stream->codec; if ( ! codec_context ) continue; AVCodec *codec = avcodec_find_decoder( codec_context->codec_id ); if ( ! codec ) continue; snprintf( key, sizeof(key), "meta.media.%d.stream.type", i ); // Determine the type and obtain the first index of each type switch( codec_context->codec_type ) { case CODEC_TYPE_VIDEO: if ( *video_index < 0 ) *video_index = i; mlt_properties_set( meta_media, key, "video" ); snprintf( key, sizeof(key), "meta.media.%d.stream.frame_rate", i ); mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->r_frame_rate ) ); #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(21<<8)+0) snprintf( key, sizeof(key), "meta.media.%d.stream.sample_aspect_ratio", i ); mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->sample_aspect_ratio ) ); #endif snprintf( key, sizeof(key), "meta.media.%d.codec.pix_fmt", i ); mlt_properties_set( meta_media, key, avcodec_get_pix_fmt_name( codec_context->pix_fmt ) ); snprintf( key, sizeof(key), "meta.media.%d.codec.sample_aspect_ratio", i ); mlt_properties_set_double( meta_media, key, av_q2d( codec_context->sample_aspect_ratio ) ); break; case CODEC_TYPE_AUDIO: if ( *audio_index < 0 ) *audio_index = i; mlt_properties_set( meta_media, key, "audio" ); #if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0)) snprintf( key, sizeof(key), "meta.media.%d.codec.sample_fmt", i ); mlt_properties_set( meta_media, key, avcodec_get_sample_fmt_name( codec_context->sample_fmt ) ); #endif snprintf( key, sizeof(key), "meta.media.%d.codec.sample_rate", i ); mlt_properties_set_int( meta_media, key, codec_context->sample_rate ); snprintf( key, sizeof(key), "meta.media.%d.codec.channels", i ); mlt_properties_set_int( meta_media, key, codec_context->channels ); break; default: break; } // snprintf( key, sizeof(key), "meta.media.%d.stream.time_base", i ); // mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->time_base ) ); snprintf( key, sizeof(key), "meta.media.%d.codec.name", i ); mlt_properties_set( meta_media, key, codec->name ); #if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(55<<8)+0)) snprintf( key, sizeof(key), "meta.media.%d.codec.long_name", i ); mlt_properties_set( meta_media, key, codec->long_name ); #endif snprintf( key, sizeof(key), "meta.media.%d.codec.bit_rate", i ); mlt_properties_set_int( meta_media, key, codec_context->bit_rate ); // snprintf( key, sizeof(key), "meta.media.%d.codec.time_base", i ); // mlt_properties_set_double( meta_media, key, av_q2d( codec_context->time_base ) ); snprintf( key, sizeof(key), "meta.media.%d.codec.profile", i ); mlt_properties_set_int( meta_media, key, codec_context->profile ); snprintf( key, sizeof(key), "meta.media.%d.codec.level", i ); mlt_properties_set_int( meta_media, key, codec_context->level ); } return meta_media; }
/** * Gets the AVPacket stored in _packet, and decodes all the samples it can from it, * putting them in _buffer, the total number of bytes written begin stored in _dataSize. */ int AudioLoader::decodePacket() { /* E_DEBUG(EAlgorithm, "-----------------------------------------------------"); E_DEBUG(EAlgorithm, "decoding packet of " << _packet.size << " bytes"); E_DEBUG(EAlgorithm, "pts: " << _packet.pts << " - dts: " << _packet.dts); //" - pos: " << pkt->pos); E_DEBUG(EAlgorithm, "flags: " << _packet.flags); E_DEBUG(EAlgorithm, "duration: " << _packet.duration); */ int len = 0; // buff is an offset in our output buffer, it points to where we should start // writing the next decoded samples int16_t* buff = _buffer; #if !HAVE_SWRESAMPLE if (_audioConvert) { buff = _buff1; } #endif // _dataSize gets the size of the buffer, in bytes _dataSize = FFMPEG_BUFFER_SIZE*sizeof(int16_t); // _dataSize input = number of bytes available for write in buff // output = number of bytes actually written (actual: S16 data) //E_DEBUG(EAlgorithm, "decode_audio_frame, available bytes in buffer = " << _dataSize); len = decode_audio_frame(_audioCtx, buff, &_dataSize, &_packet); if (len < 0) { // only print error msg when file is not an mp3, because mp3 streams can have tag // frames (id3v2?) which libavcodec tries to read as audio anyway, and we don't want // to print an error message for that... if (_audioCtx->codec_id == CODEC_ID_MP3) { E_DEBUG(EAlgorithm, "AudioLoader: invalid frame, probably an mp3 tag frame, skipping it"); } else { E_WARNING("AudioLoader: error while decoding, skipping frame"); } return 0; } if (_dataSize <= 0) { // No data yet, get more frames //cout << "no data yet, get more frames" << endl; _dataSize = 0; return 0; } #if !HAVE_SWRESAMPLE if (_audioConvert) { // this assumes that all audio is interleaved in the first channel // it works as we're only doing sample format conversion, but we // should be very careful const void* ibuf[6] = { buff }; void* obuf[6] = { _buff2 }; int istride[6] = { av_get_bytes_per_sample(_audioCtx->sample_fmt) }; int ostride[6] = { av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) }; int totalsamples = _dataSize / istride[0]; // == num_samp_per_channel * num_channels if (av_audio_convert(_audioConvert, obuf, ostride, ibuf, istride, totalsamples) < 0) { ostringstream msg; msg << "AudioLoader: Error converting " << " from " << avcodec_get_sample_fmt_name(_audioCtx->sample_fmt) << " to " << avcodec_get_sample_fmt_name(SAMPLE_FMT_S16); throw EssentiaException(msg); } // when entering the current block, dataSize contained the size in bytes // that the audio was taking in its native format. Now it needs to be set // to the size of the audio we're returning, after conversion _dataSize = totalsamples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); memcpy(_buffer, _buff2, _dataSize); } #endif if (len != _packet.size) { // FIXME: investigate why this happens and whether it is a big issue // (looks like it only loses silent samples at the end of files) // more than 1 frame in a packet, happens a lot with flac for instance... E_WARNING("AudioLoader: more than 1 frame in packet, dropping remaining bytes..."); E_WARNING("at sample index: " << output("audio").totalProduced()); E_WARNING("decoded samples: " << len); E_WARNING("packet size: " << _packet.size); } return len; }