From 156f40773fae82ec9fe8b5c7ad2615d8fa60c22e Mon Sep 17 00:00:00 2001 From: Comment Date: Sun, 17 Mar 2013 19:17:29 +0000 Subject: implementing decoder --- rotord/rotor.cpp | 124 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 86 insertions(+), 38 deletions(-) (limited to 'rotord/rotor.cpp') diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index feb4a6c..281671e 100644 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -31,7 +31,8 @@ void Render_context::runTask() { state=ANALYSING_AUDIO; //audio_analyser.process(audio_filename); //vampHost::runPlugin("","qm-vamp-plugins","qm-tempotracker", "",0, audio_filename, cerr,true); - load_audio(audio_filename); + vector proc; + load_audio(audio_filename,proc); state=AUDIO_READY; } @@ -290,42 +291,11 @@ Command_response Render_context::session_command(const std::vector& //YES //http://blog.tomaka17.com/2012/03/libavcodeclibavformat-tutorial/ - -static int open_codec_context(int *stream_idx,AVFormatContext *fmt_ctx, enum AVMediaType type) -{ - int ret; - AVStream *st; - AVCodecContext *dec_ctx = NULL; - AVCodec *dec = NULL; - ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); - if (ret < 0) { - fprintf(stderr, "Could not find %s stream in input file \n", - av_get_media_type_string(type)); - return ret; - } else { - *stream_idx = ret; - st = fmt_ctx->streams[*stream_idx]; - /* find decoder for the stream */ - dec_ctx = st->codec; - dec = avcodec_find_decoder(dec_ctx->codec_id); - cerr << "Looking for decoder for codec "<< dec_ctx->codec_id< processors){ //load audio data from file //what's the best way to use this? the model is background processing, and we want to update a progress bar //could pass a function pointer to call when each chunk of data becomes available? @@ -341,19 +311,19 @@ bool Render_context::load_audio(string &filename){ auto avFormatPtr = avFormat.get(); if (avformat_open_input(&avFormatPtr,filename.c_str(),nullptr, nullptr) != 0) { - cerr <<"Error while calling avformat_open_input (probably invalid file format)" << endl; + cerr <<"Rotor: Error while calling avformat_open_input (probably invalid file format)" << endl; return false; } if (avformat_find_stream_info(avFormat.get(), nullptr) < 0) { - cerr << "Error while calling avformat_find_stream_info" << endl; + cerr << "Rotor: Error while calling avformat_find_stream_info" << endl; return false; } av_dump_format(avFormat.get(), 0, 0, false); AVStream* stream = nullptr; - for (auto i = 0; i < avFormat->nb_streams; ++i) { + for (unsigned int i = 0; i < avFormat->nb_streams; ++i) { if (avFormat->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { // we've found a video stream! stream = avFormat->streams[i]; @@ -361,11 +331,89 @@ bool Render_context::load_audio(string &filename){ } } if (!stream) { - cerr <<"Didn't find any audio stream in the file"<< endl; + cerr <<"Rotor: Didn't find any audio stream in the file"<< endl; return false; } + // getting the required codec structure + const auto codec = avcodec_find_decoder(stream->codec->codec_id); + if (codec == nullptr) { + cerr <<"Rotor: Audio codec not available"<< endl; + return false; + } + + // allocating a structure + std::shared_ptr audioCodec(avcodec_alloc_context3(codec), [](AVCodecContext* c) { avcodec_close(c); av_free(c); }); + + /* extradata??? + // we need to make a copy of videoStream->codec->extradata and give it to the context + // make sure that this vector exists as long as the avVideoCodec exists + std::vector codecContextExtraData(stream->codec->extradata, stream->codec->extradata + stream->codec->extradata_size); + audioCodec->extradata = reinterpret_cast(codecContextExtraData.data()); + audioCodec->extradata_size = codecContextExtraData.size(); + + // initializing the structure by opening the codec + if (avcodec_open2(avVideoCodec.get(), codec, nullptr) < 0) { + cerr <<"Rotor: Could not open codec"<< endl; + return false; + } + */ + + Packet packet(avFormat.get()); + if (packet.packet.data == nullptr) { + //done + return true; + } + + do { + packet.reset(avFormat.get()); + if (packet.packet.stream_index != stream->index) + continue; // the packet is not about the video stream we want, let's jump again the start of the loop + } while(0); + + // allocating an AVFrame + std::shared_ptr avFrame(avcodec_alloc_frame(), &av_free); + + // the current packet of data + Packet packet; + // data in the packet of data already processed + size_t offsetInData = 0; + + // the decoding loop, running until EOF + while (true) { + // reading a packet using libavformat + if (offsetInData >= packet.packet.size) { + do { + packet.reset(avFormat.get()); + if (packet.stream_index != videoStream->index) + continue; + } while(0); + } + + // preparing the packet that we will send to libavcodec + AVPacket packetToSend; + packetToSend.data = packet.packet.data + offsetInData; + packetToSend.size = packet.packet.size - offsetInData; + + // sending data to libavcodec + int isFrameAvailable = 0; + const auto processedLength = avcodec_decode_video2(avVideoCodec.get(), avFrame.get(), &isFrameAvailable, &packetToSend); + if (processedLength < 0) { + av_free_packet(&packet); + throw std::runtime_error("Error while processing the data"); + } + offsetInData += processedLength; + + // processing the image if available + if (isFrameAvailable) { + // display image on the screen + + // sleeping until next frame + const auto msToWait = avVideoContext->ticks_per_frame * 1000 * avVideoContext->time_base.num / avVideoContext->time_base.den; + std::this_thread::sleep(std::chrono::milliseconds(msToWait)); + } + } return true; } -- cgit v1.2.3