void
WavFileReader::updateFrameCount()
{
    QMutexLocker locker(&m_mutex);

    size_t prevCount = m_fileInfo.frames;

    if (m_file) {
        sf_close(m_file);
        m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo);
        if (!m_file || m_fileInfo.channels <= 0) {
            std::cerr << "WavFileReader::updateFrameCount: Failed to open file at \"" << m_path << "\" ("
                      << sf_strerror(m_file) << ")" << std::endl;
        }
    }

//    SVDEBUG << "WavFileReader::updateFrameCount: now " << m_fileInfo.frames << endl;

    m_frameCount = m_fileInfo.frames;

    if (m_channelCount == 0) {
        m_channelCount = m_fileInfo.channels;
        m_sampleRate = m_fileInfo.samplerate;
    }

    if (m_frameCount != prevCount) {
//        std::cerr << "frameCountChanged" << std::endl;
        emit frameCountChanged();
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void FrameAnimationControl::setNumFrames(int numFrames)
{
    m_numFrames = numFrames < 0 ? 0 : numFrames;
    
    emit frameCountChanged(m_numFrames);

    if (m_currentFrame >= numFrames ) m_currentFrame = 0; // Should we emit frameChanged ?

}
void SimulationLayerConcatenation::appendSimulationLayer(std::shared_ptr<SimulationLayer> sl)
{
    // TODO: Check compatibility with other frames
    const int layerID = layers_.size();
    sl->setLayerId(layerId_);
    layers_.emplace_back(std::move(sl));
    connect(layers_.back().get(), &SimulationLayer::frameCountChanged,
            [this, layerID] (int frameCount) {
        frameCount = transform_.transformBack(frameCount);
        const frameNumber_t base = getLayerBaseFrameNumber(layerID);
        if (frameCount_ < base + frameCount) {
            frameCount_ = base + frameCount;
            emit frameCountChanged(frameCount_);
        }
    });
}
void PanoramaTracker::run() {
  while (isRunning() && m_scaled.size() <= MAX_TRACKER_FRAMES) {
    QScopedPointer<QtCamGstSample> sample(m_input->sample());

    if (!sample) {
      continue;
    }

    if (!Tracker::isInitialized()) {
      QSize size = QSize(sample->width(), sample->height());
      int m_width = size.width() > 720 ? size.width() / 8 : size.width() / 4;
      int m_height = size.width() > 720 ? size.height() / 8 : size.height() / 4;
      m_inputSize = size;

      // TODO: This should be 5.0 but we fail to stitch sometimes if we set it to 5
      if (!Tracker::initialize(m_width, m_height, 2.0f)) {
	emit error(Panorama::ErrorTrackerInit);
	return;
      }
    }

    // Now we can process the sample:
    const guint8 *src = sample->data();

    QScopedArrayPointer<guint8>
      dst(new guint8[m_inputSize.width() * m_inputSize.height() * 3 / 2]);
    enum libyuv::FourCC fmt;

    switch (sample->format()) {
    case GST_VIDEO_FORMAT_UYVY:
      fmt = libyuv::FOURCC_UYVY;
      break;
    default:
      qCritical() << "Unsupported color format";
      emit error(Panorama::ErrorTrackerFormat);
      return;
    }

    guint8 *y = dst.data(),
      *u = y + m_inputSize.width() * m_inputSize.height(),
      *v = u + m_inputSize.width()/2 * m_inputSize.height()/2;

    if (ConvertToI420(src, sample->size(),
		      y, m_inputSize.width(),
		      u, m_inputSize.width() / 2,
		      v, m_inputSize.width() / 2,
		      0, 0,
		      m_inputSize.width(), m_inputSize.height(),
		      m_inputSize.width(), m_inputSize.height(),
		      libyuv::kRotate0, fmt) != 0) {
      emit error(Panorama::ErrorTrackerConvert);
      return;
    }

    QScopedArrayPointer<guint8> scaled(new guint8[m_width * m_height * 3 / 2]);
    guint8 *ys = scaled.data(),
      *us = ys + m_width * m_height,
      *vs = us + m_width/2 * m_height/2;

    // Now scale:
    // No need for error checking because the function always returns 0
    libyuv::I420Scale(y, m_inputSize.width(),
		      u, m_inputSize.width()/2,
		      v, m_inputSize.width()/2,
		      m_inputSize.width(), m_inputSize.height(),
		      ys, m_width,
		      us, m_width/2,
		      vs, m_width/2,
		      m_width, m_height,
		      libyuv::kFilterBilinear);

    int err = addFrame(scaled.data());

    if (err >= 0) {
      m_scaled.push_back(scaled.take());
      m_frames.push_back(dst.take());
      emit frameCountChanged();
    }
  }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void FrameAnimationControl::setNumFrames(int numFrames)
{
    m_numFrames = numFrames < 0 ? 0 : numFrames;
    emit frameCountChanged(m_numFrames);
}