const boost::iterator_range<const uint8_t*> image_data() { { tbb::mutex::scoped_lock lock(mutex_); if(!image_data_->data()) { image_data_.get()->wait(*ogl_); ogl_->invoke([=]{image_data_.get()->map();}, high_priority); } } auto ptr = static_cast<const uint8_t*>(image_data_->data()); return boost::iterator_range<const uint8_t*>(ptr, ptr + image_data_->size()); }
std::shared_ptr<AVFrame> poll() { if(packets_.empty()) return nullptr; auto packet = packets_.front(); if(packet->data == nullptr) { if(codec_context_->codec->capabilities & CODEC_CAP_DELAY) { auto video = decode(packet); if(video) return video; } packets_.pop(); file_frame_number_ = static_cast<size_t>(packet->pos); avcodec_flush_buffers(codec_context_.get()); return flush_video(); } packets_.pop(); return decode(packet); }
std::shared_ptr<AVFrame> decode(safe_ptr<AVPacket> pkt) { std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free); int frame_finished = 0; THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, pkt.get()), "[video_decoder]"); // If a decoder consumes less then the whole packet then something is wrong // that might be just harmless padding at the end, or a problem with the // AVParser or demuxer which puted more then one frame in a AVPacket. if(frame_finished == 0) return nullptr; is_progressive_ = !decoded_frame->interlaced_frame; if(decoded_frame->repeat_pict > 0) CASPAR_LOG(warning) << "[video_decoder] Field repeat_pict not implemented."; ++file_frame_number_; // This ties the life of the decoded_frame to the packet that it came from. For the // current version of ffmpeg (0.8 or c17808c) the RAW_VIDEO codec returns frame data // owned by the packet. return std::shared_ptr<AVFrame>(decoded_frame.get(), [decoded_frame, pkt](AVFrame*){}); }