// File: cpearce[P]OggIndex/src/Decoder.cpp
// Function: DecodeIndex(std::map<unsigned int, std::vector<KeyFrameInfo, std::allocator<KeyFrameInfo>>*, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, std::vector<KeyFrameInfo, std::allocator<KeyFrameInfo>>*>>>&, ogg_packet*)
bool DecodeIndex(KeyFrameIndex& index, ogg_packet* packet) {
  assert(IsIndexPacket(packet));
  ogg_uint32_t serialno = LEUint32(packet->packet + INDEX_SERIALNO_OFFSET);
  ogg_int64_t numKeyPoints = LEUint64(packet->packet + INDEX_NUM_KEYPOINTS_OFFSET);
  ogg_int64_t time_denom = LEInt64(packet->packet + INDEX_TIME_DENOM_OFFSET);
  ogg_int64_t time_multiplier = 1000;

  // Ensure that the packet's not smaller or significantly larger than
  // we expect. These cases denote a malicious or invalid num_key_points
  // field.
  ogg_int64_t min_packet_size = INDEX_KEYPOINT_OFFSET + numKeyPoints * MIN_KEY_POINT_SIZE;
  if (packet->bytes < min_packet_size) {
    // Packet is less than the theoretical minimum size. This means that the
    // num_key_points field is too large for the packet to possibly contain as
    // many packets as it claims to, so the num_key_points field is probably
    // malicious. Don't try decoding this file, we may run out of memory.
    cerr << "WARNING: Possibly malicious number of key points reported in index packet." << endl;
    return false;
  }
  ogg_int64_t max_packet_size = INDEX_KEYPOINT_OFFSET + numKeyPoints * MAX_KEY_POINT_SIZE;
  if (max_packet_size > INT_MAX) {
    cerr << "ERROR: I can't handle index sizes greater than 2^32." << endl;
    return false;
  }

  if (time_denom == 0) {
    cerr << "WARNING: Index packet for stream " << serialno
         << " has 0 timestamp denominator." << endl;
    return false;
  }

  vector<KeyFrameInfo>* keypoints = new vector<KeyFrameInfo>();
  keypoints->reserve((ogg_int32_t)numKeyPoints);
    
  /* Read in key points. */
  unsigned char* p = packet->packet + INDEX_KEYPOINT_OFFSET;
  ogg_int64_t offset = 0;
  ogg_int64_t time = 0;
  for (ogg_int64_t i=0; i<numKeyPoints; i++) {
    assert(p < packet->packet + packet->bytes);

    ogg_int64_t offset_delta = 0;
    p = ReadVariableLength(p, &offset_delta);
    offset += offset_delta;

    assert(p < packet->packet + packet->bytes);
    ogg_int64_t time_delta = 0;
    p = ReadVariableLength(p, &time_delta);
    time += time_delta;
    ogg_int64_t time_ms = (time * time_multiplier) / time_denom;    
    
    keypoints->push_back(KeyFrameInfo(offset, time_ms));
  }
  
  index[serialno] = keypoints;
  
  assert(index[serialno] == keypoints);
  
  return true;
}

// Assembly:
subq $0xb8, %rsp
movq %rdi, 0xa8(%rsp)
movq %rsi, 0xa0(%rsp)
movq 0xa0(%rsp), %rdi
callq 0x15ec0
testb $0x1, %al
jne 0x62fa
jmp 0x62fc
jmp 0x631b
leaq 0x16ed1(%rip), %rdi     # 0x1d1d4
leaq 0x16d03(%rip), %rsi     # 0x1d00d
movl $0x406, %edx            # imm = 0x406
leaq 0x16ed4(%rip), %rcx     # 0x1d1ea
callq 0x5280
movq 0xa0(%rsp), %rax
movq (%rax), %rdi
addq $0x6, %rdi
callq 0x168b0
movl %eax, 0x9c(%rsp)
movq 0xa0(%rsp), %rax
movq (%rax), %rdi
addq $0xa, %rdi
callq 0x16ba0
movq %rax, 0x90(%rsp)
movq 0xa0(%rsp), %rax
movq (%rax), %rdi
addq $0x12, %rdi
callq 0x16cc0
movq %rax, 0x88(%rsp)
movq $0x3e8, 0x80(%rsp) # imm = 0x3E8
movq 0x90(%rsp), %rax
shlq %rax
addq $0x2a, %rax
movq %rax, 0x78(%rsp)
movq 0xa0(%rsp), %rax
movq 0x8(%rax), %rax
cmpq 0x78(%rsp), %rax
jge 0x63d0
movq 0x21c48(%rip), %rdi     # 0x27ff0
leaq 0x16e6b(%rip), %rsi     # 0x1d21a
callq 0x53d0
movq %rax, %rdi
movq 0x21c02(%rip), %rsi     # 0x27fc0
callq 0x5430
movb $0x0, 0xb7(%rsp)
jmp 0x66a5
imulq $0x18, 0x90(%rsp), %rax
addq $0x2a, %rax
movq %rax, 0x70(%rsp)
cmpq $0x7fffffff, 0x70(%rsp) # imm = 0x7FFFFFFF
jle 0x641c
movq 0x21bfc(%rip), %rdi     # 0x27ff0
leaq 0x16e6a(%rip), %rsi     # 0x1d265
callq 0x53d0
movq %rax, %rdi
movq 0x21bb6(%rip), %rsi     # 0x27fc0
callq 0x5430
movb $0x0, 0xb7(%rsp)
jmp 0x66a5
cmpq $0x0, 0x88(%rsp)
jne 0x6474
movq 0x21bc2(%rip), %rdi     # 0x27ff0
leaq 0x16e65(%rip), %rsi     # 0x1d29a
callq 0x53d0
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x5560
movq %rax, %rdi
leaq 0x16e69(%rip), %rsi     # 0x1d2bc
callq 0x53d0
movq %rax, %rdi
movq 0x21b5e(%rip), %rsi     # 0x27fc0
callq 0x5430
movb $0x0, 0xb7(%rsp)
jmp 0x66a5
movl $0x18, %edi
callq 0x53e0
movq %rax, %rdi
movq %rdi, 0x18(%rsp)
xorl %esi, %esi
movl $0x18, %edx
callq 0x5230
movq 0x18(%rsp), %rdi
callq 0x6950
movq 0x18(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rdi
movq 0x90(%rsp), %rax
movslq %eax, %rsi
callq 0x6ca0
movq 0xa0(%rsp), %rax
movq (%rax), %rax
addq $0x2a, %rax
movq %rax, 0x60(%rsp)
movq $0x0, 0x58(%rsp)
movq $0x0, 0x50(%rsp)
movq $0x0, 0x48(%rsp)
movq 0x48(%rsp), %rax
cmpq 0x90(%rsp), %rax
jge 0x6636
movq 0x60(%rsp), %rax
movq 0xa0(%rsp), %rcx
movq (%rcx), %rcx
movq 0xa0(%rsp), %rdx
addq 0x8(%rdx), %rcx
cmpq %rcx, %rax
jae 0x6520
jmp 0x653f
leaq 0x16db3(%rip), %rdi     # 0x1d2da
leaq 0x16adf(%rip), %rsi     # 0x1d00d
movl $0x42c, %edx            # imm = 0x42C
leaq 0x16cb0(%rip), %rcx     # 0x1d1ea
callq 0x5280
movq $0x0, 0x40(%rsp)
movq 0x60(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x12eb0
movq %rax, 0x60(%rsp)
movq 0x40(%rsp), %rax
addq 0x58(%rsp), %rax
movq %rax, 0x58(%rsp)
movq 0x60(%rsp), %rax
movq 0xa0(%rsp), %rcx
movq (%rcx), %rcx
movq 0xa0(%rsp), %rdx
addq 0x8(%rdx), %rcx
cmpq %rcx, %rax
jae 0x658e
jmp 0x65ad
leaq 0x16d45(%rip), %rdi     # 0x1d2da
leaq 0x16a71(%rip), %rsi     # 0x1d00d
movl $0x432, %edx            # imm = 0x432
leaq 0x16c42(%rip), %rcx     # 0x1d1ea
callq 0x5280
movq $0x0, 0x38(%rsp)
movq 0x60(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x12eb0
movq %rax, 0x60(%rsp)
movq 0x38(%rsp), %rax
addq 0x50(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rax
imulq 0x80(%rsp), %rax
cqto
idivq 0x88(%rsp)
movq %rax, 0x30(%rsp)
movq 0x68(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x58(%rsp), %rsi
movq 0x30(%rsp), %rdx
leaq 0x20(%rsp), %rdi
callq 0x6de0
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x6db0
movq 0x48(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x48(%rsp)
jmp 0x64ea
movq 0x68(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0xa8(%rsp), %rdi
leaq 0x9c(%rsp), %rsi
callq 0x6e10
movq 0x8(%rsp), %rcx
movq %rcx, (%rax)
movq 0xa8(%rsp), %rdi
leaq 0x9c(%rsp), %rsi
callq 0x6e10
movq (%rax), %rax
cmpq 0x68(%rsp), %rax
jne 0x667e
jmp 0x669d
leaq 0x16c78(%rip), %rdi     # 0x1d2fd
leaq 0x16981(%rip), %rsi     # 0x1d00d
movl $0x43d, %edx            # imm = 0x43D
leaq 0x16b52(%rip), %rcx     # 0x1d1ea
callq 0x5280
movb $0x1, 0xb7(%rsp)
movb 0xb7(%rsp), %al
andb $0x1, %al
addq $0xb8, %rsp
retq
nopw %cs:(%rax,%rax)