Ejemplo n.º 1
0
// Parse a 'FRGM' chunk and any image bearing chunks that immediately follow.
// 'fragment_chunk_size' is the previously validated, padded chunk size.
static ParseStatus ParseFragment(WebPDemuxer* const dmux,
                                 uint32_t fragment_chunk_size) {
  const int frame_num = 1;  // All fragments belong to the 1st (and only) frame.
  const int is_fragmented = !!(dmux->feature_flags_ & FRAGMENTS_FLAG);
  const uint32_t frgm_payload_size = fragment_chunk_size - FRGM_CHUNK_SIZE;
  int added_fragment = 0;
  MemBuffer* const mem = &dmux->mem_;
  Frame* frame;
  ParseStatus status =
      NewFrame(mem, FRGM_CHUNK_SIZE, fragment_chunk_size, &frame);
  if (status != PARSE_OK) return status;

  frame->is_fragment_ = 1;
  frame->x_offset_ = 2 * ReadLE24s(mem);
  frame->y_offset_ = 2 * ReadLE24s(mem);

  // Store a fragment only if the 'fragments' flag is set and there is some
  // data available.
  status = StoreFrame(frame_num, frgm_payload_size, mem, frame);
  if (status != PARSE_ERROR && is_fragmented && frame->frame_num_ > 0) {
    added_fragment = AddFrame(dmux, frame);
    if (!added_fragment) {
      status = PARSE_ERROR;
    } else {
      dmux->num_frames_ = 1;
    }
  }

  if (!added_fragment) free(frame);
  return status;
}
Ejemplo n.º 2
0
// Parse a 'TILE' chunk and any image bearing chunks that immediately follow.
// 'tile_chunk_size' is the previously validated, padded chunk size.
static ParseStatus ParseTile(WebPDemuxer* const dmux,
                             uint32_t tile_chunk_size) {
  const int has_tiles = !!(dmux->feature_flags_ & TILE_FLAG);
  const uint32_t min_size = tile_chunk_size + CHUNK_HEADER_SIZE;
  int added_tile = 0;
  MemBuffer* const mem = &dmux->mem_;
  Frame* frame;
  ParseStatus status =
      NewFrame(mem, min_size, TILE_CHUNK_SIZE, tile_chunk_size, &frame);
  if (status != PARSE_OK) return status;

  frame->is_tile_  = 1;
  frame->x_offset_ = 2 * GetLE24s(mem);
  frame->y_offset_ = 2 * GetLE24s(mem);
  Skip(mem, tile_chunk_size - TILE_CHUNK_SIZE);  // skip any trailing data.

  // Store a (potentially partial) tile only if the tile flag is set
  // and the tile contains some data.
  status = StoreFrame(dmux->num_frames_, mem, frame);
  if (status != PARSE_ERROR && has_tiles && frame->frame_num_ > 0) {
    // Note num_frames_ is incremented only when all tiles have been consumed.
    added_tile = AddFrame(dmux, frame);
    if (!added_tile) status = PARSE_ERROR;
  }

  if (!added_tile) free(frame);
  return status;
}
Ejemplo n.º 3
0
bool AVIDump::Start(HWND hWnd, int w, int h)
{
	s_emu_wnd = hWnd;
	s_file_count = 0;

	s_width = w;
	s_height = h;

	s_last_frame = CoreTiming::GetTicks();

	if (SConfig::GetInstance().m_SYSCONF->GetData<u8>("IPL.E60"))
		s_frame_rate = 60; // always 60, for either pal60 or ntsc
	else
		s_frame_rate = VideoInterface::TargetRefreshRate; // 50 or 60, depending on region

	// clear CFR frame cache on start, not on file create (which is also segment switch)
	SetBitmapFormat();
	StoreFrame(nullptr);

	//Dragonbane: Setup file reading if last side
	bool lastSide = false;

	if (Movie::cmp_isRunning)
	{
		if (Movie::cmp_leftFinished || Movie::cmp_rightFinished)
			lastSide = true;

		if (lastSide)
		{
			tempFileCount = 0;
			s_stopTempFile = false;
			std::string movie_file_name = GetCurrDumpFile(tempFileCount, true);

			if (File::Exists(movie_file_name) && Movie::cmp_startTimerFrame > Movie::cmp_curentBranchFrame) //Dragonbane: Open temp file for reading
			{
				HRESULT h2 = AVIFileOpenA(&s_file_temp, movie_file_name.c_str(), OF_READ, nullptr);
				HRESULT h3 = AVIFileGetStream(s_file_temp, &s_stream_temp, streamtypeVIDEO, 0);

				s_last_key_temp = 1; //Skip first key frame as its always black

				s_getFrame_temp = AVIStreamGetFrameOpen(s_stream_temp, &s_bitmap);

				if (!s_getFrame_temp)
				{
					PanicAlertT("Your chosen compression codec can not be decompressed again! Can't create video comparison!");
					Movie::CancelComparison();
				}
			}
		}
	}

	return CreateFile();
}
Ejemplo n.º 4
0
static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
  const size_t min_size = CHUNK_HEADER_SIZE;
  MemBuffer* const mem = &dmux->mem_;
  Frame* frame;
  ParseStatus status;
  int image_added = 0;

  if (dmux->frames_ != NULL) return PARSE_ERROR;
  if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
  if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;

  frame = (Frame*)calloc(1, sizeof(*frame));
  if (frame == NULL) return PARSE_ERROR;

  // For the single image case we allow parsing of a partial frame, but we need
  // at least CHUNK_HEADER_SIZE for parsing.
  status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame);
  if (status != PARSE_ERROR) {
    const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG);
    // Clear any alpha when the alpha flag is missing.
    if (!has_alpha && frame->img_components_[1].size_ > 0) {
      frame->img_components_[1].offset_ = 0;
      frame->img_components_[1].size_ = 0;
      frame->has_alpha_ = 0;
    }

    // Use the frame width/height as the canvas values for non-vp8x files.
    // Also, set ALPHA_FLAG if this is a lossless image with alpha.
    if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) {
      dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
      dmux->canvas_width_ = frame->width_;
      dmux->canvas_height_ = frame->height_;
      dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0;
    }
    if (!AddFrame(dmux, frame)) {
      status = PARSE_ERROR;  // last frame was left incomplete
    } else {
      image_added = 1;
      dmux->num_frames_ = 1;
    }
  }

  if (!image_added) free(frame);
  return status;
}
Ejemplo n.º 5
0
Json::Value FileSaver::StoreLayer(Layer* layer, const std::string& dir, 
								  bool single)
{
	Json::Value value;

	value["name"] = layer->GetName();

	const std::map<int, KeyFrame*>& frames = layer->GetAllFrames();
	std::vector<KeyFrame*> all_frames;
	all_frames.reserve(frames.size());
	std::map<int, KeyFrame*>::const_iterator itr = frames.begin();
	for (size_t i = 0; itr != frames.end(); ++itr, ++i) {
		value["frame"][i] = StoreFrame(itr->second, dir, single);
		all_frames.push_back(itr->second);
	}

	return value;
}
Ejemplo n.º 6
0
// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
// 'frame_chunk_size' is the previously validated, padded chunk size.
static ParseStatus ParseAnimationFrame(
    WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
  const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
  const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
  int added_frame = 0;
  int bits;
  MemBuffer* const mem = &dmux->mem_;
  Frame* frame;
  ParseStatus status =
      NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
  if (status != PARSE_OK) return status;

  frame->x_offset_       = 2 * ReadLE24s(mem);
  frame->y_offset_       = 2 * ReadLE24s(mem);
  frame->width_          = 1 + ReadLE24s(mem);
  frame->height_         = 1 + ReadLE24s(mem);
  frame->duration_       = ReadLE24s(mem);
  bits = ReadByte(mem);
  frame->dispose_method_ =
      (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
  frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
  if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) {
    free(frame);
    return PARSE_ERROR;
  }

  // Store a frame only if the animation flag is set there is some data for
  // this frame is available.
  status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame);
  if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) {
    added_frame = AddFrame(dmux, frame);
    if (added_frame) {
      ++dmux->num_frames_;
    } else {
      status = PARSE_ERROR;
    }
  }

  if (!added_frame) free(frame);
  return status;
}
Ejemplo n.º 7
0
static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
  const size_t min_size = CHUNK_HEADER_SIZE;
  MemBuffer* const mem = &dmux->mem_;
  Frame* frame;
  ParseStatus status;

  if (dmux->frames_ != NULL) return PARSE_ERROR;
  if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
  if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;

  frame = (Frame*)calloc(1, sizeof(*frame));
  if (frame == NULL) return PARSE_ERROR;

  status = StoreFrame(1, &dmux->mem_, frame);
  if (status != PARSE_ERROR) {
    const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG);
    // Clear any alpha when the alpha flag is missing.
    if (!has_alpha && frame->img_components_[1].size_ > 0) {
      frame->img_components_[1].offset_ = 0;
      frame->img_components_[1].size_ = 0;
    }

    // Use the frame width/height as the canvas values for non-vp8x files.
    if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) {
      dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
      dmux->canvas_width_ = frame->width_;
      dmux->canvas_height_ = frame->height_;
    }
    AddFrame(dmux, frame);
    dmux->num_frames_ = 1;
  } else {
    free(frame);
  }

  return status;
}
Ejemplo n.º 8
0
// Parse a 'FRM ' chunk and any image bearing chunks that immediately follow.
// 'frame_chunk_size' is the previously validated, padded chunk size.
static ParseStatus ParseFrame(
    WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
  const int has_frames = !!(dmux->feature_flags_ & ANIMATION_FLAG);
  const uint32_t min_size = frame_chunk_size + CHUNK_HEADER_SIZE;
  int added_frame = 0;
  MemBuffer* const mem = &dmux->mem_;
  Frame* frame;
  ParseStatus status =
      NewFrame(mem, min_size, FRAME_CHUNK_SIZE, frame_chunk_size, &frame);
  if (status != PARSE_OK) return status;

  frame->x_offset_ = 2 * GetLE24s(mem);
  frame->y_offset_ = 2 * GetLE24s(mem);
  frame->width_    = 1 + GetLE24s(mem);
  frame->height_   = 1 + GetLE24s(mem);
  frame->duration_ = 1 + GetLE24s(mem);
  Skip(mem, frame_chunk_size - FRAME_CHUNK_SIZE);  // skip any trailing data.
  if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) {
    return PARSE_ERROR;
  }

  // Store a (potentially partial) frame only if the animation flag is set
  // and there is some data in 'frame'.
  status = StoreFrame(dmux->num_frames_ + 1, mem, frame);
  if (status != PARSE_ERROR && has_frames && frame->frame_num_ > 0) {
    added_frame = AddFrame(dmux, frame);
    if (added_frame) {
      ++dmux->num_frames_;
    } else {
      status = PARSE_ERROR;
    }
  }

  if (!added_frame) free(frame);
  return status;
}
Ejemplo n.º 9
0
void AVIDump::AddFrame(const u8* data, int w, int h)
{
	static bool shown_error = false;
	if ((w != s_bitmap.biWidth || h != s_bitmap.biHeight) && !shown_error)
	{
		PanicAlertT("You have resized the window while dumping frames.\n"
		            "Nothing can be done to handle this properly.\n"
		            "Your video will likely be broken.");
		shown_error = true;

		s_bitmap.biWidth = w;
		s_bitmap.biHeight = h;
	}
	// no timecodes, instead dump each frame as many/few times as needed to keep sync
	u64 one_cfr = SystemTimers::GetTicksPerSecond() / VideoInterface::TargetRefreshRate;
	int nplay = 0;
	s64 delta;
	if (!s_start_dumping && s_last_frame <= SystemTimers::GetTicksPerSecond())
	{
		delta = CoreTiming::GetTicks();
		s_start_dumping = true;
	}
	else
	{
		delta = CoreTiming::GetTicks() - s_last_frame;
	}
	bool b_frame_dumped = false;
	// try really hard to place one copy of frame in stream (otherwise it's dropped)
	if (delta > (s64)one_cfr * 1 / 10) // place if 1/10th of a frame space
	{
		delta -= one_cfr;
		nplay++;
	}
	// try not nearly so hard to place additional copies of the frame
	while (delta > (s64)one_cfr * 9 / 10) // place if 9/10th of a frame space
	{
		delta -= one_cfr;
		nplay++;
	}
	while (nplay--)
	{
		if (!b_frame_dumped)
		{
			AVIStreamWrite(s_stream_compressed, s_frame_count++, 1, GetFrame(), s_bitmap.biSizeImage, AVIIF_KEYFRAME, nullptr, &s_byte_buffer);
			b_frame_dumped = true;
		}
		else
		{
			AVIStreamWrite(s_stream, s_frame_count++, 1, nullptr, 0, 0, nullptr, nullptr);
		}
		s_total_bytes += s_byte_buffer;
		// Close the recording if the file is larger than 2gb
		// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
		if (s_total_bytes >= 2000000000)
		{
			CloseFile();
			s_file_count++;
			CreateFile();
		}
	}
	StoreFrame(data);
	s_last_frame = CoreTiming::GetTicks();
}