#include "libavaudioloader.h" bool libav::Audioloader::setup(const std::string &filename){ av_register_all(); frame = avcodec_alloc_frame(); if (!frame) { std::cout << "Error allocating the frame" << std::endl; return false; } formatContext = NULL; if (avformat_open_input(&formatContext, filename.c_str(), NULL, NULL) != 0) { av_free(frame); std::cout << "Error opening the file" << std::endl; return false; } if (avformat_find_stream_info(formatContext, NULL) < 0) { av_free(frame); avformat_close_input(&formatContext); std::cout << "Error finding the stream info" << std::endl; return false; } audioStream = NULL; for (unsigned int i = 0; i < formatContext->nb_streams; ++i) { if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audioStream = formatContext->streams[i]; break; } } if (audioStream == NULL) { av_free(frame); avformat_close_input(&formatContext); std::cout << "Could not find any audio stream in the file" << std::endl; return false; } codecContext = audioStream->codec; codecContext->codec = avcodec_find_decoder(codecContext->codec_id); if (codecContext->codec == NULL) { av_free(frame); avformat_close_input(&formatContext); std::cout << "Couldn't find a proper decoder" << std::endl; return false; } else if (avcodec_open2(codecContext, codecContext->codec, NULL) != 0) { av_free(frame); avformat_close_input(&formatContext); std::cout << "Couldn't open the context with the decoder" << std::endl; return false; } av_dump_format(formatContext, 0, 0, false); //avformat.h line 1256 int samples = ((formatContext->duration + 5000)*codecContext->sample_rate)/AV_TIME_BASE; std::cout << "This stream has " << codecContext->channels << " channels, a sample rate of " << codecContext->sample_rate << "Hz and "<sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ") "<index) { //int bytes = avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); // Some frames rely on multiple packets, so we have to make sure the frame is finished before // we can use it } // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory av_free_packet(&packet); } return frame; } AVPacket* libav::Audioloader::get_packet() { if (!ready) return nullptr; int ret=av_read_frame(formatContext, &packet); if (ret<0) { std::cerr << "finished with code "<index) //{ //int bytes = // avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); // Some frames rely on multiple packets, so we have to make sure the frame is finished before // we can use it //} // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory //av_free_packet(&packet);????? //} return &packet; } /* // Some codecs will cause frames to be buffered up in the decoding process. If the CODEC_CAP_DELAY flag // is set, there can be buffered up frames that need to be flushed, so we'll do that if (codecContext->codec->capabilities & CODEC_CAP_DELAY) { av_init_packet(&packet); // Decode all the remaining frames in the buffer, until the end is reached int frameFinished = 0; int bytes = avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); while (bytes >= 0 && frameFinished) { for (auto p: processors) { p->process_frame(frame->data[0],frame->nb_samples); } mutex.lock(); progress=((double)sample_processed)/samples; mutex.unlock(); } } cerr << "finished processing: "<0){ for (int i=0;inb_samples))*channels)>buffer.size()){ int m=buffer.size(); int s=((sample_end+std::max(num,frame->nb_samples))*channels); buffer.reserve(s); std::cerr << "audioloader reserved buffer to " << s << std::endl; for (int i=m;inb_samples;i++) { for (int j=0;jchannels)+j]= ((uint16_t*) frame->buf[j]->data)[i]; //buffer[(j*frame->channels)+(sample_end+i)]= ((uint16_t*) frame->buf[j]->data)[i]; ??planar?? nope } } sample_end+=frame->nb_samples; } else { for (int i=sample_end;inb_samples)*frame->channels)<num) { sample_start=num; } else { sample_start=0; } return (uint16_t*)(&buffer[0]); } bool libav::Audioloader::close() { av_free(frame); avcodec_close(codecContext); avformat_close_input(&formatContext); return true; }