bool ThumbFinder::seekBackward()
{
    int inc;
    int64_t newFrame;
    int64_t currentFrame = (m_currentPTS - m_startPTS) / m_frameTime;

    inc = SeekAmounts[m_currentSeek].amount;
    if (inc == -1)
        inc = -1;
    else if (inc == -2)
    {
        // seek to previous cut point
        frm_dir_map_t::const_iterator it;
        int pos = 0;
        for (it = m_deleteMap.begin(); it != m_deleteMap.end(); ++it)
        {
            if (it.key() >= (uint64_t)currentFrame)
                break;

            pos = it.key();
        }

        // seek to next cutpoint
        m_offset = 0;
        seekToFrame(pos, false);
        return true;
    }
    else
        inc = (int) (-inc * ceil(m_fps));

    newFrame = currentFrame + inc - m_offset;
    seekToFrame(newFrame);

    return true;
}
Exemple #2
0
bool VQAPlayer::setBeginAndEndFrame(int begin, int end, int repeatsCount, int loopSetMode, void (*callback)(void *, int, int), void *callbackData) {
#if BLADERUNNER_DEBUG_CONSOLE
	debug("VQAPlayer::setBeginAndEndFrame(%i, %i, %i, %i), streamLoaded = %i", begin, end, repeatsCount, loopSetMode, _s != nullptr);
#endif

	if (repeatsCount < 0) {
		repeatsCount = -1;
	}

	if (_repeatsCount == 0 && loopSetMode == kLoopSetModeEnqueue) {
		loopSetMode = kLoopSetModeImmediate;
	}

	//TODO: there is code in original game which deals with changing loop at start of loop, is it nescesarry? loc_46EA04

	_frameBegin = begin;

	if (loopSetMode == kLoopSetModeJustStart) {
		_repeatsCount = repeatsCount;
	} else if (loopSetMode == kLoopSetModeEnqueue) {
		_repeatsCountQueued = repeatsCount;
		_frameEndQueued = end;
	} else if (loopSetMode == kLoopSetModeImmediate) {
		_repeatsCount = repeatsCount;
		_frameEnd = end;
		seekToFrame(begin);
	}

	_callbackLoopEnded = callback;
	_callbackData = callbackData;

	return true;
}
Exemple #3
0
bool AVISurface::startAtFrame(int frameNumber) {
	if (isPlaying())
		// If it's already playing, then don't allow it
		return false;

	if (frameNumber == -1)
		// Default to starting frame of first movie range
		frameNumber = _movieRangeInfo.front()->_startFrame;
	if (_isReversed && frameNumber == (int)_decoder->getFrameCount())
		--frameNumber;

	// Start the playback
	_decoder->start();

	// Seek to the starting frame
	seekToFrame(frameNumber);

	// If we're in reverse playback, set the decoder to play in reverse
	if (_isReversed)
		_decoder->setRate(Common::Rational(-1));

	renderFrame();

	return true;
}
Exemple #4
0
void RobotDecoder::doRobot() {
	if (_status != kRobotStatusPlaying) {
		return;
	}

	if (!_syncFrame) {
		if (_cueForceShowFrame != -1) {
			_currentFrameNo = _cueForceShowFrame;
			_cueForceShowFrame = -1;
		} else {
			const int nextFrameNo = calculateNextFrameNo(_delayTime.predictedTicks());
			if (nextFrameNo < _currentFrameNo) {
				return;
			}
			_currentFrameNo = nextFrameNo;
		}
	}

	if (_currentFrameNo >= _numFramesTotal) {
		const int finalFrameNo = _numFramesTotal - 1;
		if (_previousFrameNo == finalFrameNo) {
			_status = kRobotStatusEnd;
			if (_hasAudio) {
				_audioList.stopAudio();
				_frameRate = _normalFrameRate;
				_hasAudio = false;
			}
			return;
		} else {
			_currentFrameNo = finalFrameNo;
		}
	}

	if (_currentFrameNo == _previousFrameNo) {
		_audioList.submitDriverMax();
		return;
	}

	if (_hasAudio) {
		for (int candidateFrameNo = _previousFrameNo + _maxSkippablePackets + 1; candidateFrameNo < _currentFrameNo; candidateFrameNo += _maxSkippablePackets + 1) {

			_audioList.submitDriverMax();

			int audioPosition, audioSize;
			if (readAudioDataFromRecord(candidateFrameNo, _audioBuffer, audioPosition, audioSize)) {
				_audioList.addBlock(audioPosition, audioSize, _audioBuffer);
			}
		}
		_audioList.submitDriverMax();
	}

	_delayTime.startTiming();
	seekToFrame(_currentFrameNo);
	doVersion5();
	if (_hasAudio) {
		_audioList.submitDriverMax();
	}
}
void ThumbFinder::gridItemChanged(MythUIButtonListItem *item)
{
    (void) item;

    int itemNo = m_imageGrid->GetCurrentPos();
    ThumbImage *thumb = m_thumbList.at(itemNo);
    if (thumb)
          seekToFrame(thumb->frame);
}
Exemple #6
0
void AVISurface::setFrame(int frameNumber) {
	// If playback was in process, stop it
	if (isPlaying())
		stop();

	// Ensure the frame number is valid
	if (frameNumber >= (int)_decoder->getFrameCount())
		frameNumber = _decoder->getFrameCount() - 1;

	seekToFrame(frameNumber);
	renderFrame();
}
Exemple #7
0
const Graphics::Surface *RlfAnimation::getFrameData(uint frameNumber) {
	assert(!_stream);
	assert(frameNumber < _frameCount);

	// Since this method is so expensive, first check to see if we can use
	// getNextFrame() it's cheap.
	if ((int)frameNumber == _currentFrame) {
		return &_currentFrameBuffer;
	} else if (_currentFrame + 1 == (int)frameNumber) {
		return getNextFrame();
	}

	seekToFrame(frameNumber);
	return &_currentFrameBuffer;
}
Exemple #8
0
bool AVISurface::handleEvents(CMovieEventList &events) {
	if (!isPlaying())
		return true;

	CMovieRangeInfo *info = _movieRangeInfo.front();
	_priorFrame = _currentFrame;
	_currentFrame += _isReversed ? -1 : 1;

	int newFrame = _currentFrame;
	if ((info->_isReversed && newFrame < info->_endFrame) ||
		(!info->_isReversed && newFrame > info->_endFrame)) {
		if (info->_isRepeat) {
			newFrame = info->_startFrame;
		} else {
			info->getMovieEnd(events);
			_movieRangeInfo.remove(info);
			delete info;

			if (_movieRangeInfo.empty()) {
				// No more ranges, so stop playback
				stop();
			} else {
				// Not empty, so move onto new first one
				info = _movieRangeInfo.front();
				newFrame = info->_startFrame;
				setReversed(info->_isReversed);
			}
		}
	}

	if (isPlaying()) {
		if (newFrame != getFrame()) {
			// The frame has been changed, so move to new position
			seekToFrame(newFrame);
			renderFrame();
		}

		// Get any events for the given position
		info->getMovieFrame(events, newFrame);
		return renderFrame();
	} else {
		return false;
	}
}
Exemple #9
0
bool AVISurface::startAtFrame(int frameNumber) {
	if (isPlaying())
		// If it's already playing, then don't allow it
		return false;

	if (frameNumber == -1)
		// Default to starting frame of first movie range
		frameNumber = _movieRangeInfo.front()->_startFrame;

	// Get the initial frame
	seekToFrame(frameNumber);
	renderFrame();

	// Start the playback
	_decoders[0]->start();
	if (_decoders[1])
		_decoders[1]->start();

	return true;
}
Exemple #10
0
void LadybugWidget::keyPressEvent(QKeyEvent* e)
{
  if (e->key() >= Qt::Key_1 && e->key() <= Qt::Key_5)
  {
    int i = e->key()-Qt::Key_1;

    // invert camera on/off setting
    setCameraState(i, !cameraState(i));

    if (mPaused)
      updateVideo(getSingleFrame(mCurrentFrame));
  }

  switch (e->key())
  {
    case Qt::Key_Space:
      pause();
      break;
    case Qt::Key_Left:
      seekToFrame(mCurrentFrame-1);
      break;
    case Qt::Key_Right:
      seekToFrame(mCurrentFrame+1);
      break;
    case Qt::Key_Home:
      seekToFrame(0);
      break;
    case Qt::Key_End:
      seekToFrame(mStream.framesCount()-1);
      break;
    case Qt::Key_PageUp:
      seekToFrame(mCurrentFrame-25);
      break;
    case Qt::Key_PageDown:
      seekToFrame(mCurrentFrame+25);
      break;

    // %%% seek to random position (for testing)
    case Qt::Key_S:
      {
        uint msecs = rand() % (mStream.framesCount() / 15 * 1000);
        printf("RANDOM TIME SEEK! %d ms\n", msecs);
        seekToTime(msecs);
        break;
      }
  }
}
Exemple #11
0
void QuickTimeDecoder::seekToTime(Audio::Timestamp time) {
	// TODO: Audio-only seeking (or really, have QuickTime sounds)
	if (_videoStreamIndex < 0)
		error("Audio-only seeking not supported");

	// Try to find the last frame that should have been decoded
	uint32 frame = 0;
	Audio::Timestamp totalDuration(0, _streams[_videoStreamIndex]->time_scale);
	bool done = false;

	for (int32 i = 0; i < _streams[_videoStreamIndex]->stts_count && !done; i++) {
		for (int32 j = 0; j < _streams[_videoStreamIndex]->stts_data[i].count; j++) {
			totalDuration = totalDuration.addFrames(_streams[_videoStreamIndex]->stts_data[i].duration);
			if (totalDuration > time) {
				done = true;
				break;
			}
			frame++;
		}
	}

	seekToFrame(frame);
}
Exemple #12
0
void QuickTimeDecoder::seekToTime(Audio::Timestamp time) {
	// Use makeQuickTimeStream() instead
	if (_videoTrackIndex < 0)
		error("Audio-only seeking not supported");

	// Try to find the last frame that should have been decoded
	uint32 frame = 0;
	Audio::Timestamp totalDuration(0, _tracks[_videoTrackIndex]->timeScale);
	bool done = false;

	for (int32 i = 0; i < _tracks[_videoTrackIndex]->timeToSampleCount && !done; i++) {
		for (int32 j = 0; j < _tracks[_videoTrackIndex]->timeToSample[i].count; j++) {
			totalDuration = totalDuration.addFrames(_tracks[_videoTrackIndex]->timeToSample[i].duration);
			if (totalDuration > time) {
				done = true;
				break;
			}
			frame++;
		}
	}

	seekToFrame(frame);
}
Exemple #13
0
void SeekableBinkDecoder::seekToTime(Audio::Timestamp time) {
	// Try to find the last frame that should have been decoded
	Common::Rational frame = time.msecs() * getFrameRate() / 1000;
	seekToFrame(frame.toInt());
}
Exemple #14
0
bool ThumbFinder::getThumbImages()
{
    if (!getFileDetails(m_archiveItem))
    {
        LOG(VB_GENERAL, LOG_ERR, 
            QString("ThumbFinder:: Failed to get file details for %1")
                .arg(m_archiveItem->filename));
        return false;
    }

    if (!initAVCodec(m_archiveItem->filename))
        return false;

    if (m_archiveItem->type == "Recording")
        loadCutList();

    // calculate the file duration taking the cut list into account
    m_finalDuration = calcFinalDuration();

    QString origFrameFile = m_frameFile;

    m_updateFrame = true;
    getFrameImage();

    int chapterLen;
    if (m_thumbCount)
        chapterLen = m_finalDuration / m_thumbCount;
    else
        chapterLen = m_finalDuration;

    QString thumbList = "";
    m_updateFrame = false;

    // add title thumb
    m_frameFile = m_thumbDir + "/title.jpg";
    ThumbImage *thumb = nullptr;

    if (m_thumbList.size() > 0)
    {
        // use the thumb details in the thumbList if already available
        thumb = m_thumbList.at(0);
    }

    if (!thumb)
    {
        // no thumb available create a new one
        thumb = new ThumbImage;
        thumb->filename = m_frameFile;
        thumb->frame = (int64_t) 0;
        thumb->caption = "Title";
        m_thumbList.append(thumb);
    }
    else
        m_frameFile = thumb->filename;

    seekToFrame(thumb->frame);
    getFrameImage();

    new MythUIButtonListItem(m_imageGrid, thumb->caption, thumb->filename);

    qApp->processEvents();

    for (int x = 1; x <= m_thumbCount; x++)
    {
        m_frameFile = m_thumbDir + QString("/chapter-%1.jpg").arg(x);

        thumb = nullptr;

        if (m_archiveItem->thumbList.size() > x)
        {
            // use the thumb details in the archiveItem if already available
            thumb = m_archiveItem->thumbList.at(x);
        }

        if (!thumb)
        {
            QString time;
            int chapter, hour, min, sec;

            chapter = chapterLen * (x - 1);
            hour = chapter / 3600;
            min = (chapter % 3600) / 60;
            sec = chapter % 60;
            time = time.sprintf("%02d:%02d:%02d", hour, min, sec);

            int64_t frame = (int64_t) (chapter * ceil(m_fps));

            // no thumb available create a new one
            thumb = new ThumbImage;
            thumb->filename = m_frameFile;
            thumb->frame = frame;
            thumb->caption = time;
            m_thumbList.append(thumb);
        }
        else
            m_frameFile = thumb->filename;

        seekToFrame(thumb->frame);
        qApp->processEvents();
        getFrameImage();
        qApp->processEvents();
        new MythUIButtonListItem(m_imageGrid, thumb->caption, thumb->filename);
        qApp->processEvents();
    }

    m_frameFile = origFrameFile;
    seekToFrame(0);

    m_updateFrame = true;

    m_imageGrid->SetRedraw();

    SetFocusWidget(m_imageGrid);

    return true;
}
Exemple #15
0
void RobotDecoder::showFrame(const uint16 frameNo, const uint16 newX, const uint16 newY, const uint16 newPriority) {
	debugC(kDebugLevelVideo, "Show frame %d (%d %d %d)", frameNo, newX, newY, newPriority);

	if (newX != kUnspecified) {
		_position.x = newX;
	}

	if (newY != kUnspecified) {
		_position.y = newY;
	}

	if (newPriority != kUnspecified) {
		_priority = newPriority;
	}

	_currentFrameNo = frameNo;
	pause();

	if (frameNo != _previousFrameNo) {
		seekToFrame(frameNo);
		doVersion5(false);
	} else {
		for (RobotScreenItemList::size_type i = 0; i < _screenItemList.size(); ++i) {
			if (_isHiRes) {
				SciBitmap &bitmap = *_segMan->lookupBitmap(_celHandles[i].bitmapId);

				const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
				const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
				const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
				const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;

				if (scriptWidth == kLowResX && scriptHeight == kLowResY) {
					const Ratio lowResToScreenX(screenWidth, kLowResX);
					const Ratio lowResToScreenY(screenHeight, kLowResY);
					const Ratio screenToLowResX(kLowResX, screenWidth);
					const Ratio screenToLowResY(kLowResY, screenHeight);

					const int16 scaledX = _originalScreenItemX[i] + (_position.x * lowResToScreenX).toInt();
					const int16 scaledY1 = _originalScreenItemY[i] + (_position.y * lowResToScreenY).toInt();
					const int16 scaledY2 = scaledY1 + bitmap.getHeight() - 1;

					const int16 lowResX = (scaledX * screenToLowResX).toInt();
					const int16 lowResY = (scaledY2 * screenToLowResY).toInt();

					bitmap.setOrigin(Common::Point(
						(scaledX - (lowResX * lowResToScreenX).toInt()) * -1,
						(lowResY * lowResToScreenY).toInt() - scaledY1
					));

					_screenItemX[i] = lowResX;
					_screenItemY[i] = lowResY;
				} else {
					const int16 scaledX = _originalScreenItemX[i] + _position.x;
					const int16 scaledY = _originalScreenItemY[i] + _position.y + bitmap.getHeight() - 1;
					bitmap.setOrigin(Common::Point(0, bitmap.getHeight() - 1));
					_screenItemX[i] = scaledX;
					_screenItemY[i] = scaledY;
				}
			} else {
				_screenItemX[i] = _originalScreenItemX[i] + _position.x;
				_screenItemY[i] = _originalScreenItemY[i] + _position.y;
			}

			if (_screenItemList[i] == nullptr) {
				CelInfo32 celInfo;
				celInfo.type = kCelTypeMem;
				celInfo.bitmap = _celHandles[i].bitmapId;
				ScreenItem *screenItem = new ScreenItem(_plane->_object, celInfo);
				_screenItemList[i] = screenItem;
				screenItem->_position = Common::Point(_screenItemX[i], _screenItemY[i]);
				if (_priority == -1) {
					screenItem->_fixedPriority = false;
				} else {
					screenItem->_priority = _priority;
					screenItem->_fixedPriority = true;
				}
				g_sci->_gfxFrameout->addScreenItem(*screenItem);
			} else {
				ScreenItem *screenItem = _screenItemList[i];
				screenItem->_celInfo.bitmap = _celHandles[i].bitmapId;
				screenItem->_position = Common::Point(_screenItemX[i], _screenItemY[i]);
				if (_priority == -1) {
					screenItem->_fixedPriority = false;
				} else {
					screenItem->_priority = _priority;
					screenItem->_fixedPriority = true;
				}
				g_sci->_gfxFrameout->updateScreenItem(*screenItem);
			}
		}
	}

	_previousFrameNo = frameNo;
}
Exemple #16
0
bool ThumbFinder::keyPressEvent(QKeyEvent *event)
{
    if (GetFocusWidget()->keyPressEvent(event))
        return true;

    QStringList actions;
    bool handled = GetMythMainWindow()->TranslateKeyPress("Archive", event, actions);

    for (int i = 0; i < actions.size() && !handled; i++)
    {
        QString action = actions[i];
        handled = true;

        if (action == "MENU")
        {
            NextPrevWidgetFocus(true);
            return true;
        }

        if (action == "ESCAPE")
        {
            ShowMenu();
            return true;
        }

        if (action == "0" || action == "1" || action == "2" || action == "3" ||
            action == "4" || action == "5" || action == "6" || action == "7" ||
            action == "8" || action == "9")
        {
            m_imageGrid->SetItemCurrent(action.toInt());
            int itemNo = m_imageGrid->GetCurrentPos();
            ThumbImage *thumb = m_thumbList.at(itemNo);
            if (thumb)
                seekToFrame(thumb->frame);
            return true;
        }

        if (GetFocusWidget() == m_frameButton)
        {
            if (action == "UP")
            {
                changeSeekAmount(true);
            }
            else if (action == "DOWN")
            {
                changeSeekAmount(false);
            }
            else if (action == "LEFT")
            {
                seekBackward();
            }
            else if (action == "RIGHT")
            {
                seekForward();
            }
            else if (action == "SELECT")
            {
                updateThumb();
            }
            else
                handled = false;
        }
        else
            handled = false;
    }

    if (!handled && MythScreenType::keyPressEvent(event))
        handled = true;

    return handled;
}
Exemple #17
0
bool VideoPlayer::seekToRatio(double ratio) {
  assert(ratio >= 0.0 && ratio <= 1.0);
  const size_t frameIdx = static_cast<size_t>(std::floor(ratio * numFrames()));
  return seekToFrame(frameIdx);
}