// File: /workspace/github_cpp_makefile_star2_O1/cpearce[P]OggIndex/src/Validate.cpp
// Function: Theora::Decode(ogg_page*, long&)
virtual ogg_int64_t Decode(ogg_page* page, ogg_int64_t& end_time) {
    end_time = -1;
    if ((ogg_uint32_t)ogg_page_serialno(page) != mSerial) {
      return -1;
    }
    ogg_int64_t start_time = INT_MAX;

    assert(AllBufferedGranuleposInvalid());

    const int shift = mInfo.keyframe_granule_shift;
    ogg_packet op;
    int ret = ogg_stream_pagein(&mStreamState, page);
    assert(ret == 0);
    while ((ret = ogg_stream_packetout(&mStreamState, &op)) != 0) {
      if (ret == -1) {
        cout << "WARNING: Theora decoder out of sync!" << endl;
        continue;
      }
      if (!mReadHeaders) {
        ogg_int32_t ret = th_decode_headerin(&mInfo,
                                             &mComment,
                                             &mSetup,
                                             &op);
        if (ret > 0) {
          mHeaderPacketsRead++;
          mReadHeaders = (mHeaderPacketsRead == 3);
          if (mReadHeaders) {
            mCtx = th_decode_alloc(&mInfo, mSetup);
            assert(mCtx != NULL);
            mFrameDuration = (1000 * mInfo.fps_denominator) / mInfo.fps_numerator;
          }
          continue;
        } else {
          cout << "th_decode_headerin returned " << ret << endl;
          return false;
        }
      }

      PacketInfo p;
      p.granulepos = op.granulepos;
      p.isKeyFrame = th_packet_iskeyframe(&op) != 0;

      mBuffer.push_back(p);

      if (p.granulepos == -1) {
        continue;
      }

      assert(op.granulepos == -1 || op.granulepos == ogg_page_granulepos(page));

      // We've got buffered packets, and the last one has a known
      // granulepos. Use its granulepos to calculate the other granulepos.          
      list<PacketInfo>::reverse_iterator rev_itr = mBuffer.rbegin();
      PacketInfo *prev = &(*rev_itr);
      rev_itr++;
      while (rev_itr != mBuffer.rend()) {
        PacketInfo* p = &(*rev_itr);
        assert(prev->granulepos != -1);
        ogg_int64_t granulepos;
        if (p->isKeyFrame) {
          granulepos =
            (th_granule_frame(mCtx, prev->granulepos) + TheoraVersion(&mInfo,3,2,1) - 1) << shift;
        } else {
          if (prev->isKeyFrame) {
            // The previous frame is a keyframe, so we can't just subtract 1
            // from the "keyframe offset" part of its granulepos, as it
            // doesn't have one! So fake it, take the keyframe offset as the
            // max possible keyframe offset. This means the granulepos claims
            // that it depends on the wrong keyframe, but at least its granule
            // number will be correct, so the times we calculate from this
            // granulepos will also be correct.
            ogg_int64_t frameno = th_granule_frame(mCtx, prev->granulepos);
            ogg_int64_t max_offset = min((frameno - 1), (ogg_int64_t)(1 << shift) - 1);
            ogg_int64_t granule = frameno +
                                  TheoraVersion(&mInfo,3,2,1) - 1 - max_offset;
            assert(granule > 0);
            granulepos = (granule << shift) + max_offset;
          } else {
            assert((prev->granulepos & ((1 << shift) - 1)) > 0);
            granulepos = prev->granulepos - 1;
          }
        }
        p->granulepos = granulepos;
        assert(th_granule_frame(mCtx, p->granulepos) ==
               th_granule_frame(mCtx, prev->granulepos) - 1);
        assert(Time(p->granulepos) < Time(prev->granulepos));
        prev = p;
        rev_itr++;
      }
      assert(mBuffer.front().granulepos != -1);
      assert(mBuffer.size() > 0);

      ogg_int64_t time = NextKeyframeTime();
      if (time != -1) {
        start_time = min(time, start_time);
        end_time = start_time + mFrameDuration;
        ogg_int64_t page_end_time = Time(ogg_page_granulepos(page));
        assert(time <= page_end_time);
      }        
    }
   
    return (start_time != INT_MAX) ? start_time : -1;
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rdx, %r12
movq %rsi, %r13
movq %rdi, %r15
movq $-0x1, (%rdx)
movq %rsi, %rdi
callq 0x42d0
movq $-0x1, %rcx
cmpl 0x8(%r15), %eax
jne 0xe843
leaq 0x1a8(%r15), %rbp
movq %rbp, %rax
movq (%rax), %rax
cmpq %rbp, %rax
je 0xe3a4
cmpq $-0x1, 0x10(%rax)
je 0xe376
leaq 0x3b29(%rip), %rdi      # 0x11eb5
leaq 0x35af(%rip), %rsi      # 0x11942
leaq 0x3b2f(%rip), %rcx      # 0x11ec9
movl $0x7b, %edx
callq 0x4210
movl 0x1fc(%r15), %ebx
leaq 0x10(%r15), %r14
movq %r14, %rdi
movq %r13, %rsi
callq 0x4550
testl %eax, %eax
jne 0xe912
leaq 0x1c0(%r15), %rax
movq %rax, (%rsp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %ebx, %ecx
shll %cl, %eax
leaq 0x200(%r15), %rcx
movq %rcx, 0x50(%rsp)
leaq 0x220(%r15), %rcx
movq %rcx, 0x48(%rsp)
notl %eax
movq %rax, 0x40(%rsp)
movl $0x1, %eax
movq %rbx, 0x18(%rsp)
movl %ebx, %ecx
shll %cl, %eax
cltq
decq %rax
movq %rax, 0x38(%rsp)
movl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movq %rax, 0x8(%rsp)
movq %r14, 0x10(%rsp)
movq %r14, %rdi
leaq 0x58(%rsp), %rsi
callq 0x45a0
cmpl $-0x1, %eax
je 0xe4c5
testl %eax, %eax
je 0xe829
cmpb $0x0, 0xc(%r15)
jne 0xe56d
movq (%rsp), %rdi
movq 0x50(%rsp), %rsi
movq 0x48(%rsp), %rdx
leaq 0x58(%rsp), %rcx
callq 0x4600
movl %eax, %ebx
testl %eax, %eax
jle 0xe50c
movl 0x230(%r15), %eax
incl %eax
movl %eax, 0x230(%r15)
cmpl $0x3, %eax
sete 0xc(%r15)
jne 0xe560
movq 0x220(%r15), %rsi
movq (%rsp), %rdi
callq 0x4440
movq %rax, 0x228(%r15)
testq %rax, %rax
je 0xe8b5
imull $0x3e8, 0x1e0(%r15), %eax # imm = 0x3E8
xorl %edx, %edx
divl 0x1dc(%r15)
movq %rax, 0x238(%r15)
jmp 0xe560
movl $0x24, %edx
movq 0x8aff(%rip), %rbx      # 0x16fd0
movq %rbx, %rdi
leaq 0x3846(%rip), %rsi      # 0x11d21
callq 0x4410
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x4360
movsbl %al, %esi
movq %rbx, %rdi
callq 0x4040
movq %rax, %rdi
callq 0x4250
jmp 0xe41c
movl $0x1c, %edx
movq 0x8ab8(%rip), %r14      # 0x16fd0
movq %r14, %rdi
leaq 0x3824(%rip), %rsi      # 0x11d46
callq 0x4410
movq %r14, %rdi
movl %ebx, %esi
callq 0x46a0
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x4360
movsbl %al, %esi
movq %r14, %rdi
movq 0x10(%rsp), %r14
callq 0x4040
movq %rax, %rdi
callq 0x4250
testl %ebx, %ebx
jg 0xe41c
jmp 0xe841
movq 0x78(%rsp), %r14
leaq 0x58(%rsp), %rdi
callq 0x42a0
movl %eax, %ebx
movl $0x20, %edi
callq 0x4380
testl %ebx, %ebx
movq %r14, 0x10(%rax)
setne 0x18(%rax)
movq %rax, %rdi
movq %rbp, %rsi
callq 0x4060
incq 0x1b8(%r15)
cmpq $-0x1, %r14
movq 0x10(%rsp), %r14
je 0xe41c
movq %rbp, 0x20(%rsp)
movq %r12, 0x30(%rsp)
movq 0x78(%rsp), %rbx
cmpq $-0x1, %rbx
je 0xe5d9
movq %r13, %rdi
callq 0x4620
cmpq %rax, %rbx
jne 0xe96f
movq %r13, 0x28(%rsp)
movq 0x1a8(%r15), %rax
movq 0x1b0(%r15), %r14
cmpq %rax, %r14
movq 0x18(%rsp), %r13
je 0xe76e
leaq 0x10(%r14), %r12
movq (%r12), %rsi
cmpq $-0x1, %rsi
je 0xe896
movq 0x8(%r14), %rbp
cmpb $0x1, 0x18(%rbp)
jne 0xe64e
movq 0x228(%r15), %rdi
callq 0x40b0
movq %rax, %rbx
movq (%rsp), %rdi
movl $0x3, %esi
movl $0x2, %edx
movl $0x1, %ecx
callq 0xcab0
cltq
leaq (%rbx,%rax), %rsi
decq %rsi
movl %r13d, %ecx
shlq %cl, %rsi
jmp 0xe6c1
cmpb $0x1, 0x8(%r12)
jne 0xe6b4
movq 0x228(%r15), %rdi
callq 0x40b0
movq %rax, %rbx
leaq -0x1(%rax), %r13
movq 0x38(%rsp), %rax
cmpq %r13, %rax
cmovlq %rax, %r13
movq (%rsp), %rdi
movl $0x3, %esi
movl $0x2, %edx
movl $0x1, %ecx
callq 0xcab0
cltq
addq %rbx, %rax
movq %r13, %rsi
notq %rsi
addq %rax, %rsi
testq %rsi, %rsi
jle 0xe8f3
movq 0x18(%rsp), %rcx
shlq %cl, %rsi
addq %r13, %rsi
movq %rcx, %r13
jmp 0xe6c1
testl %esi, 0x40(%rsp)
je 0xe8d4
decq %rsi
addq $0x10, %rbp
movq %rsi, (%rbp)
movq 0x228(%r15), %rdi
callq 0x40b0
movq %rax, %rbx
movq 0x228(%r15), %rdi
movq (%r12), %rsi
callq 0x40b0
decq %rax
cmpq %rax, %rbx
jne 0xe858
movq (%rbp), %rsi
movq 0x228(%r15), %rdi
callq 0x40b0
imull $0x3e8, 0x1e0(%r15), %ecx # imm = 0x3E8
imulq %rcx, %rax
movl 0x1dc(%r15), %ecx
cqto
idivq %rcx
movq %rax, %rbx
movq (%r12), %rsi
movq 0x228(%r15), %rdi
callq 0x40b0
imull $0x3e8, 0x1e0(%r15), %ecx # imm = 0x3E8
imulq %rcx, %rax
movl 0x1dc(%r15), %ecx
cqto
idivq %rcx
cmpq %rax, %rbx
jge 0xe877
movq 0x8(%r14), %r14
movq 0x20(%rsp), %rax
movq (%rax), %rax
movq %rbp, %r12
cmpq %rax, %r14
jne 0xe5fe
cmpq $-0x1, 0x10(%rax)
je 0xe950
cmpq $0x0, 0x1b8(%r15)
movq 0x30(%rsp), %r12
movq 0x28(%rsp), %r13
movq 0x20(%rsp), %rbp
movq 0x10(%rsp), %r14
je 0xe931
movq %r15, %rdi
callq 0xe9bc
cmpq $-0x1, %rax
je 0xe41c
movq %rax, %rbx
movq 0x8(%rsp), %rcx
cmpq %rax, %rcx
cmovgeq %rax, %rcx
movq 0x238(%r15), %rax
movq %rcx, 0x8(%rsp)
addq %rcx, %rax
movq %rax, (%r12)
movq %r13, %rdi
callq 0x4620
movq 0x228(%r15), %rdi
movq %rax, %rsi
callq 0x40b0
imull $0x3e8, 0x1e0(%r15), %ecx # imm = 0x3E8
imulq %rcx, %rax
movl 0x1dc(%r15), %ecx
cqto
idivq %rcx
cmpq %rax, %rbx
jle 0xe41c
leaq 0x368e(%rip), %rdi      # 0x11e9f
leaq 0x312a(%rip), %rsi      # 0x11942
leaq 0x34c4(%rip), %rcx      # 0x11ce3
movl $0xfa, %edx
callq 0x4210
movq 0x8(%rsp), %rax
cmpq $0x7fffffff, %rax       # imm = 0x7FFFFFFF
movq $-0x1, %rcx
cmovneq %rax, %rcx
jmp 0xe843
xorl %ecx, %ecx
movq %rcx, %rax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3589(%rip), %rdi      # 0x11de8
leaq 0x30dc(%rip), %rsi      # 0x11942
leaq 0x3476(%rip), %rcx      # 0x11ce3
movl $0xed, %edx
callq 0x4210
leaq 0x35c0(%rip), %rdi      # 0x11e3e
leaq 0x30bd(%rip), %rsi      # 0x11942
leaq 0x3457(%rip), %rcx      # 0x11ce3
movl $0xee, %edx
callq 0x4210
leaq 0x3508(%rip), %rdi      # 0x11da5
leaq 0x309e(%rip), %rsi      # 0x11942
leaq 0x3438(%rip), %rcx      # 0x11ce3
movl $0xd2, %edx
callq 0x4210
leaq 0x1b0f(%rip), %rdi      # 0x103cb
leaq 0x307f(%rip), %rsi      # 0x11942
leaq 0x3419(%rip), %rcx      # 0x11ce3
movl $0xb5, %edx
callq 0x4210
leaq 0x34e1(%rip), %rdi      # 0x11dbc
leaq 0x3060(%rip), %rsi      # 0x11942
leaq 0x33fa(%rip), %rcx      # 0x11ce3
movl $0xe7, %edx
callq 0x4210
leaq 0x1ba5(%rip), %rdi      # 0x1049f
leaq 0x3041(%rip), %rsi      # 0x11942
leaq 0x33db(%rip), %rcx      # 0x11ce3
movl $0xe4, %edx
callq 0x4210
leaq 0x16eb(%rip), %rdi      # 0x10004
leaq 0x3022(%rip), %rsi      # 0x11942
leaq 0x33bc(%rip), %rcx      # 0x11ce3
movl $0xa5, %edx
callq 0x4210
leaq 0x3554(%rip), %rdi      # 0x11e8c
leaq 0x3003(%rip), %rsi      # 0x11942
leaq 0x339d(%rip), %rcx      # 0x11ce3
movl $0xf3, %edx
callq 0x4210
leaq 0x3514(%rip), %rdi      # 0x11e6b
leaq 0x2fe4(%rip), %rsi      # 0x11942
leaq 0x337e(%rip), %rcx      # 0x11ce3
movl $0xf2, %edx
callq 0x4210
leaq 0x33ed(%rip), %rdi      # 0x11d63
leaq 0x2fc5(%rip), %rsi      # 0x11942
leaq 0x335f(%rip), %rcx      # 0x11ce3
movl $0xc9, %edx
callq 0x4210