// File: cpearce[P]OggIndex/src/SkeletonEncoder.cpp
// Function: SkeletonEncoder::CorrectOffsets()
void
SkeletonEncoder::CorrectOffsets() {
  assert(mIndexPackets.size() != 0);
  ogg_int64_t fileLength = mFileLength - mOldSkeletonLength + GetTrackLength();

  // Difference in file lengths before and after indexing. We must add this
  // amount to the page offsets in the index packets, as they've changed by
  // this much.
  ogg_int64_t lengthDiff = fileLength - mFileLength;
  assert(lengthDiff == (GetTrackLength() - mOldSkeletonLength));

  // First determine by how much the file will grow when we update all the
  // offsets.
  ogg_int64_t extra_bytes = 0;
  for (ogg_uint32_t idx=0; idx<mIndexPackets.size(); idx++) {
    ogg_packet* packet = mIndexPackets[idx];
    assert(packet);
    
    if (!IsIndexPacket(packet)) {
      continue;
    }

    unsigned char* p = packet->packet + INDEX_KEYPOINT_OFFSET;
    if (p >= packet->packet + packet->bytes) {
      continue;
    }
    ogg_int64_t offset = 0;
    p = ReadVariableLength(p, &offset);

    // If increasing the first keypoint's offset field means it needs more
    // bytes to be encoded, increase the size of the index to accomodate this.
    int adjusted_bytes_required = bytes_required(offset + lengthDiff);
    int existing_bytes_required = bytes_required(offset);
    if (adjusted_bytes_required != existing_bytes_required) {
      extra_bytes += adjusted_bytes_required - existing_bytes_required;
    }
  }
  lengthDiff += extra_bytes;
  fileLength += extra_bytes;
  mContentOffset += lengthDiff;

  // Correct the offset of the first keyframe in every track by how much
  // the offsets have changed.
  for (ogg_uint32_t idx=0; idx<mIndexPackets.size(); idx++) {
    ogg_packet* packet = mIndexPackets[idx];
    assert(packet);
    
    if (!IsIndexPacket(packet)) {
      continue;
    }

    unsigned char* p = packet->packet + INDEX_KEYPOINT_OFFSET;
    if (p >= packet->packet + packet->bytes) {
      continue;
    }
    ogg_int64_t offset = 0;
    p = ReadVariableLength(p, &offset);

    ogg_uint32_t existing_checksum = LEUint32(p);
    ogg_int64_t existing_time_diff = 0;
    ReadVariableLength(p + 4, &existing_time_diff);
    ogg_int64_t existing_offset = offset;

    // If increasing the first keypoint's offset field means it needs more
    // bytes to be encoded, increase the size of the index to accomodate this.
    int adjusted_bytes_required = bytes_required(offset + lengthDiff);
    int existing_bytes_required = bytes_required(offset);
    if (adjusted_bytes_required != existing_bytes_required) {
      // We don't have enough room to write the adjusted offset back into the
      // variable-length encoded keypoint data. Make the packet bigger.
      int diff = adjusted_bytes_required - existing_bytes_required;
      unsigned char* q = new unsigned char[packet->bytes + diff];

      // Copy up to the keypoints into the new packet.
      memcpy(q, packet->packet, INDEX_KEYPOINT_OFFSET);

      // Copy from after the first keypoint's offset until the end into
      // the new packet.
      memcpy(q + INDEX_KEYPOINT_OFFSET + adjusted_bytes_required,
             packet->packet + INDEX_KEYPOINT_OFFSET + existing_bytes_required,
             packet->bytes - INDEX_KEYPOINT_OFFSET - existing_bytes_required);

      delete packet->packet;
      packet->packet = q;
      assert(mIndexPackets[idx]->packet == q);
      packet->bytes += diff;
    }

    // Write the adjusted 
    offset += lengthDiff;
    WriteVariableLength(packet->packet + INDEX_KEYPOINT_OFFSET,
                        packet->packet + packet->bytes,
                        offset);

    ogg_int64_t new_offset = 0;
    unsigned char* j = ReadVariableLength(packet->packet + INDEX_KEYPOINT_OFFSET, &new_offset);
    ogg_uint32_t new_checksum = LEUint32(j);
    ogg_int64_t new_time_diff = 0;
    ReadVariableLength(j + 4, &new_time_diff);

    assert(existing_offset + lengthDiff == new_offset);
    assert(existing_checksum == new_checksum);
    assert(existing_time_diff == new_time_diff);
  }

  // First correct the BOS packet's segment length field.
  WriteLEUint64(mIndexPackets[0]->packet + SKELETON_FILE_LENGTH_OFFSET, fileLength);

  // Correct the BOS packet's content offset field.
  WriteLEUint64(mIndexPackets[0]->packet + SKELETON_CONTENT_OFFSET, mContentOffset);

}

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xe0(%rsp)
movq 0xe0(%rsp), %rdi
movq %rdi, 0x28(%rsp)
addq $0x38, %rdi
callq 0x6980
cmpq $0x0, %rax
je 0x127fd
jmp 0x1281c
leaq 0xb9c1(%rip), %rdi      # 0x1e1c5
leaq 0xb7d9(%rip), %rsi      # 0x1dfe4
movl $0x1b6, %edx            # imm = 0x1B6
leaq 0xb9c8(%rip), %rcx      # 0x1e1df
callq 0x5280
movq 0x28(%rsp), %rdi
movq 0x20(%rdi), %rax
subq 0x28(%rdi), %rax
movq %rax, 0x18(%rsp)
callq 0x13160
movq 0x28(%rsp), %rdi
movq %rax, %rcx
movq 0x18(%rsp), %rax
addq %rcx, %rax
movq %rax, 0xd8(%rsp)
movq 0xd8(%rsp), %rax
subq 0x20(%rdi), %rax
movq %rax, 0xd0(%rsp)
movq 0xd0(%rsp), %rax
movq %rax, 0x20(%rsp)
callq 0x13160
movq 0x28(%rsp), %rdx
movq %rax, %rcx
movq 0x20(%rsp), %rax
subq 0x28(%rdx), %rcx
cmpq %rcx, %rax
jne 0x12889
jmp 0x128a8
leaq 0xb976(%rip), %rdi      # 0x1e206
leaq 0xb74d(%rip), %rsi      # 0x1dfe4
movl $0x1bd, %edx            # imm = 0x1BD
leaq 0xb93c(%rip), %rcx      # 0x1e1df
callq 0x5280
movq $0x0, 0xc8(%rsp)
movl $0x0, 0xc4(%rsp)
movq 0x28(%rsp), %rdi
movl 0xc4(%rsp), %eax
movq %rax, 0x10(%rsp)
addq $0x38, %rdi
callq 0x6980
movq %rax, %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
jae 0x12a2f
movq 0x28(%rsp), %rdi
addq $0x38, %rdi
movl 0xc4(%rsp), %eax
movl %eax, %esi
callq 0x69a0
movq (%rax), %rax
movq %rax, 0xb8(%rsp)
cmpq $0x0, 0xb8(%rsp)
je 0x12919
jmp 0x12938
leaq 0xaac2(%rip), %rdi      # 0x1d3e2
leaq 0xb6bd(%rip), %rsi      # 0x1dfe4
movl $0x1c4, %edx            # imm = 0x1C4
leaq 0xb8ac(%rip), %rcx      # 0x1e1df
callq 0x5280
movq 0xb8(%rsp), %rdi
callq 0x15ec0
testb $0x1, %al
jne 0x1294e
jmp 0x12a19
movq 0xb8(%rsp), %rax
movq (%rax), %rax
addq $0x2a, %rax
movq %rax, 0xb0(%rsp)
movq 0xb0(%rsp), %rax
movq 0xb8(%rsp), %rcx
movq (%rcx), %rcx
movq 0xb8(%rsp), %rdx
addq 0x8(%rdx), %rcx
cmpq %rcx, %rax
jb 0x1298e
jmp 0x12a19
movq $0x0, 0xa8(%rsp)
movq 0xb0(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x12eb0
movq %rax, 0xb0(%rsp)
movq 0xa8(%rsp), %rdi
addq 0xd0(%rsp), %rdi
callq 0x130b0
movl %eax, 0xa4(%rsp)
movq 0xa8(%rsp), %rdi
callq 0x130b0
movl %eax, 0xa0(%rsp)
movl 0xa4(%rsp), %eax
cmpl 0xa0(%rsp), %eax
je 0x12a17
movl 0xa4(%rsp), %eax
subl 0xa0(%rsp), %eax
cltq
addq 0xc8(%rsp), %rax
movq %rax, 0xc8(%rsp)
jmp 0x12a19
movl 0xc4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc4(%rsp)
jmp 0x128bf
movq 0x28(%rsp), %rax
movq 0xc8(%rsp), %rcx
addq 0xd0(%rsp), %rcx
movq %rcx, 0xd0(%rsp)
movq 0xc8(%rsp), %rcx
addq 0xd8(%rsp), %rcx
movq %rcx, 0xd8(%rsp)
movq 0xd0(%rsp), %rcx
addq 0x68(%rax), %rcx
movq %rcx, 0x68(%rax)
movl $0x0, 0x9c(%rsp)
movq 0x28(%rsp), %rdi
movl 0x9c(%rsp), %eax
movq %rax, 0x8(%rsp)
addq $0x38, %rdi
callq 0x6980
movq %rax, %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
jae 0x12e43
movq 0x28(%rsp), %rdi
addq $0x38, %rdi
movl 0x9c(%rsp), %eax
movl %eax, %esi
callq 0x69a0
movq (%rax), %rax
movq %rax, 0x90(%rsp)
cmpq $0x0, 0x90(%rsp)
je 0x12ad9
jmp 0x12af8
leaq 0xa902(%rip), %rdi      # 0x1d3e2
leaq 0xb4fd(%rip), %rsi      # 0x1dfe4
movl $0x1e1, %edx            # imm = 0x1E1
leaq 0xb6ec(%rip), %rcx      # 0x1e1df
callq 0x5280
movq 0x90(%rsp), %rdi
callq 0x15ec0
testb $0x1, %al
jne 0x12b0e
jmp 0x12e2d
movq 0x90(%rsp), %rax
movq (%rax), %rax
addq $0x2a, %rax
movq %rax, 0x88(%rsp)
movq 0x88(%rsp), %rax
movq 0x90(%rsp), %rcx
movq (%rcx), %rcx
movq 0x90(%rsp), %rdx
addq 0x8(%rdx), %rcx
cmpq %rcx, %rax
jb 0x12b4e
jmp 0x12e2d
movq $0x0, 0x80(%rsp)
movq 0x88(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0x12eb0
movq %rax, 0x88(%rsp)
movq 0x88(%rsp), %rdi
callq 0x168b0
movl %eax, 0x7c(%rsp)
movq $0x0, 0x70(%rsp)
movq 0x88(%rsp), %rdi
addq $0x4, %rdi
leaq 0x70(%rsp), %rsi
callq 0x12eb0
movq 0x80(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x80(%rsp), %rdi
addq 0xd0(%rsp), %rdi
callq 0x130b0
movl %eax, 0x64(%rsp)
movq 0x80(%rsp), %rdi
callq 0x130b0
movl %eax, 0x60(%rsp)
movl 0x64(%rsp), %eax
cmpl 0x60(%rsp), %eax
je 0x12d02
movl 0x64(%rsp), %eax
subl 0x60(%rsp), %eax
movl %eax, 0x5c(%rsp)
movq 0x90(%rsp), %rax
movq 0x8(%rax), %rdi
movslq 0x5c(%rsp), %rax
addq %rax, %rdi
callq 0x5030
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rdi
movq 0x90(%rsp), %rax
movq (%rax), %rsi
movl $0x2a, %edx
callq 0x5340
movq 0x50(%rsp), %rdi
addq $0x2a, %rdi
movslq 0x64(%rsp), %rax
addq %rax, %rdi
movq 0x90(%rsp), %rax
movq (%rax), %rsi
addq $0x2a, %rsi
movslq 0x60(%rsp), %rax
addq %rax, %rsi
movq 0x90(%rsp), %rax
movq 0x8(%rax), %rdx
subq $0x2a, %rdx
movslq 0x60(%rsp), %rax
subq %rax, %rdx
callq 0x5340
movq 0x90(%rsp), %rax
movq (%rax), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x12c98
movq (%rsp), %rdi
movl $0x1, %esi
callq 0x5400
movq 0x28(%rsp), %rdi
movq 0x50(%rsp), %rcx
movq 0x90(%rsp), %rax
movq %rcx, (%rax)
addq $0x38, %rdi
movl 0x9c(%rsp), %eax
movl %eax, %esi
callq 0x69a0
movq (%rax), %rax
movq (%rax), %rax
cmpq 0x50(%rsp), %rax
jne 0x12cce
jmp 0x12ced
leaq 0xb567(%rip), %rdi      # 0x1e23c
leaq 0xb308(%rip), %rsi      # 0x1dfe4
movl $0x208, %edx            # imm = 0x208
leaq 0xb4f7(%rip), %rcx      # 0x1e1df
callq 0x5280
movslq 0x5c(%rsp), %rcx
movq 0x90(%rsp), %rax
addq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
movq 0xd0(%rsp), %rax
addq 0x80(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x90(%rsp), %rax
movq (%rax), %rdi
addq $0x2a, %rdi
movq 0x90(%rsp), %rax
movq (%rax), %rsi
movq 0x90(%rsp), %rax
addq 0x8(%rax), %rsi
movq 0x80(%rsp), %rdx
callq 0x14140
movq $0x0, 0x48(%rsp)
movq 0x90(%rsp), %rax
movq (%rax), %rdi
addq $0x2a, %rdi
leaq 0x48(%rsp), %rsi
callq 0x12eb0
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rdi
callq 0x168b0
movl %eax, 0x3c(%rsp)
movq $0x0, 0x30(%rsp)
movq 0x40(%rsp), %rdi
addq $0x4, %rdi
leaq 0x30(%rsp), %rsi
callq 0x12eb0
movq 0x68(%rsp), %rax
addq 0xd0(%rsp), %rax
cmpq 0x48(%rsp), %rax
jne 0x12db4
jmp 0x12dd3
leaq 0xb4a1(%rip), %rdi      # 0x1e25c
leaq 0xb222(%rip), %rsi      # 0x1dfe4
movl $0x218, %edx            # imm = 0x218
leaq 0xb411(%rip), %rcx      # 0x1e1df
callq 0x5280
movl 0x7c(%rsp), %eax
cmpl 0x3c(%rsp), %eax
jne 0x12ddf
jmp 0x12dfe
leaq 0xb4a1(%rip), %rdi      # 0x1e287
leaq 0xb1f7(%rip), %rsi      # 0x1dfe4
movl $0x219, %edx            # imm = 0x219
leaq 0xb3e6(%rip), %rcx      # 0x1e1df
callq 0x5280
movq 0x70(%rsp), %rax
cmpq 0x30(%rsp), %rax
jne 0x12e0c
jmp 0x12e2b
leaq 0xb496(%rip), %rdi      # 0x1e2a9
leaq 0xb1ca(%rip), %rsi      # 0x1dfe4
movl $0x21a, %edx            # imm = 0x21A
leaq 0xb3b9(%rip), %rcx      # 0x1e1df
callq 0x5280
jmp 0x12e2d
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x12a7f
movq 0x28(%rsp), %rdi
addq $0x38, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x69a0
movq (%rax), %rax
movq (%rax), %rdi
addq $0x40, %rdi
movq 0xd8(%rsp), %rsi
callq 0x16ad0
movq 0x28(%rsp), %rdi
addq $0x38, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x69a0
movq %rax, %rcx
movq 0x28(%rsp), %rax
movq (%rcx), %rcx
movq (%rcx), %rdi
addq $0x48, %rdi
movq 0x68(%rax), %rsi
callq 0x16ad0
addq $0xe8, %rsp
retq
nopw %cs:(%rax,%rax)