// File: /workspace/github_cpp_makefile_star2_O2/cpearce[P]OggIndex/src/Decoder.cpp
// Function: TheoraDecoder::Decode(ogg_page*, long)
bool Decode(ogg_page* page, ogg_int64_t offset) {
    assert((ogg_uint32_t)ogg_page_serialno(page) == mSerial);
    if (GotAllHeaders()) {
      Page record;
      record.num_packets = CountPacketStarts(page);
      record.offset = offset;
      mPages.push_back(record);
    }
 
    int ret = ogg_stream_pagein(&mState, page);
    ogg_int64_t page_granulepos = ogg_page_granulepos(page);
    assert(ret == 0);

    ogg_packet packet;
    int num_packets = 0;
    vector<Frame> frames;
    while ((ret = ogg_stream_packetout(&mState, &packet)) != 0) {
      if (ret == -1) {
        cerr << "WARNING: Lost sync decoding packets on theora page "
             << mPages.size() << endl;
        continue;
      }
      num_packets++;
      if (!GotAllHeaders()) {
        // Read Headers...
        ret = th_decode_headerin(&mInfo,
                                 &mComment,
                                 &mSetup,
                                 &packet);
        assert(ret > 0);
        if (ret > 0) {
          // Read Theora header.
          mHeadersRead++;
        }
        if (GotAllHeaders()) {
          // Read all headers, setup decoder context.
          mCtx = th_decode_alloc(&mInfo, mSetup);
          assert(mCtx != NULL);
        }
        if (gOptions.GetDumpPackets()) {
          cout << "[T] ver="
               << (int)mInfo.version_major << "."
               << (int)mInfo.version_minor << "."
               << (int)mInfo.version_subminor << " "
               << TheoraHeaderType(&packet) << " packet"
               << (packet.e_o_s ? " eos" : "")
               << endl;
        }
        continue;
      }      

      if (mFirstPacketno == -1) {
        mFirstPacketno = packet.packetno;
      }
      
      const int shift = mInfo.keyframe_granule_shift;

      // Packet should only have a granulepos if the page does.
      assert(page_granulepos != -1 || packet.granulepos == -1);
      assert(packet.granulepos == -1 || packet.granulepos == page_granulepos);
      
      // We've not yet determined the granulepos of the first (or previous)
      // packet. Remember the packet, even if it's not a keyframe so that
      // we can backtrack to get all packets' start time.
      frames.push_back(Frame(packet));

      if (packet.granulepos == -1) {
        // We've stored the packet, once we find one with a non -1 granulepos
        // we can find the first packet's granulepos.
        continue;
      }
        
      // We know a packet's granulepos, use it to tag the packets buffered
      // before it so that they have valid granulepos.
      for (int i=(int)frames.size()-2; i>=0; i--) {
        ogg_int64_t prev_granulepos = frames[i+1].granulepos;
        assert(prev_granulepos != -1);
        ogg_int64_t granulepos = -1;
        if (frames[i].is_keyframe) {
          ogg_int64_t frame = th_granule_frame(mCtx, prev_granulepos) +
                              TheoraVersion(&mInfo,3,2,1) - 1;
          // 3.2.0 streams store the frame index in the granule position.
          // 3.2.1 and later store the frame count. th_granule_frame() returns
          // the frame index, so |frame| can be 0 when we're theora version
          // 3.2.0 or less.
          assert(frame > 0 || !TheoraVersion(&mInfo,3,2,1));
          granulepos = frame << shift;
        } else {
          if (frames[i+1].is_keyframe) {
            // The successor 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 (probably)
            // overshoots and claims that it depends on a frame before its actual
            // 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); // We must have positive granulepos...
            granulepos = (granule << shift) + max_offset;
          } else {
            // We must be offset by more than 1 frame for this to work.
            assert((prev_granulepos & ((1 << shift) - 1)) > 0);
            granulepos = prev_granulepos - 1;
          }
        }
        // This frame's granule number should be one less than the previous.
        assert(th_granule_frame(mCtx, granulepos) ==
                th_granule_frame(mCtx, prev_granulepos) - 1);
        frames[i].granulepos = granulepos;
      }
      // Now all packets have a known time.
      if (mStartTime == -1) {
        mStartTime = StartTime(frames.front().granulepos);
      }
      assert(mStartTime >= 0);
      mEndTime = EndTime(frames.back().granulepos);
      assert(mEndTime >= mStartTime);

      // Print/log packets before we remove non-keyframe packets.
      for (unsigned i=0; i<frames.size(); i++) {
        DumpPacket(frames[i]);
      }

      // Add keyframes to the final frame list.
      for (unsigned i=0; i<frames.size(); i++) {
        if (frames[i].is_keyframe) {
          mFrames.push_back(frames[i]);
        }
      }
    } // end while packetout


    if (num_packets != ogg_page_packets(page)) {
      cerr << "WARNING: Fewer packets finished on theora page "
           << mPages.size() << " than expected." << endl;
    }
    return true;
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movq %rdx, %r14
movq %rdi, %rbx
movq %rsi, 0x30(%rsp)
movq %rsi, %rdi
callq 0x42c0
cmpl 0x1a0(%rbx), %eax
jne 0x5b82
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x18(%rax)
testb %al, %al
je 0x5551
movq 0x30(%rsp), %rdi
callq 0xaf95
leaq 0x80(%rsp), %rsi
movl %eax, 0x8(%rsi)
movq %r14, (%rsi)
leaq 0x248(%rbx), %rdi
callq 0x5fba
leaq 0x8(%rbx), %rdi
movq %rdi, 0x48(%rsp)
movq 0x30(%rsp), %r14
movq %r14, %rsi
callq 0x4500
movl %eax, %ebp
movq %r14, %rdi
callq 0x45c0
testl %ebp, %ebp
jne 0x5ba1
movq %rax, %r15
xorps %xmm0, %xmm0
leaq 0x10(%rsp), %rax
movaps %xmm0, (%rax)
andq $0x0, 0x10(%rax)
leaq 0x1b8(%rbx), %rax
movq %rax, (%rsp)
leaq 0x1f8(%rbx), %rax
movq %rax, 0x50(%rsp)
leaq 0x218(%rbx), %rax
movq %rax, 0x40(%rsp)
leaq 0x260(%rbx), %rax
movq %rax, 0x68(%rsp)
movl $0x0, 0xc(%rsp)
leaq 0x80(%rsp), %r12
movq 0xfa1e(%rip), %r13      # 0x14ff0
movq 0x48(%rsp), %r14
movq %r15, 0x70(%rsp)
movq %r14, %rdi
movq %r12, %rsi
callq 0x4550
cmpl $-0x1, %eax
jne 0x561f
movq %r13, %rdi
leaq 0x8d99(%rip), %rsi      # 0xe38f
callq 0x4340
movq 0x250(%rbx), %rsi
subq 0x248(%rbx), %rsi
sarq $0x4, %rsi
movq %rax, %rdi
callq 0x4240
movq %rax, %rdi
callq 0x41b0
jmp 0x55dc
testl %eax, %eax
je 0x5a75
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x18(%rax)
incl 0xc(%rsp)
testb %al, %al
je 0x585b
cmpq $-0x1, 0x240(%rbx)
jne 0x5655
movq 0xa8(%rsp), %rax
movq %rax, 0x240(%rbx)
cmpq $-0x1, %r15
setne %cl
movq 0xa0(%rsp), %rax
cmpq $-0x1, %rax
sete %dl
orb %cl, %dl
je 0x5bdf
cmpq $-0x1, %rax
sete %cl
cmpq %r15, %rax
sete %al
orb %cl, %al
je 0x5bfe
movl 0x1f4(%rbx), %eax
movq %rax, 0x38(%rsp)
leaq 0xb0(%rsp), %rbp
movq %rbp, %rdi
movq %r12, %rsi
callq 0x5fd8
leaq 0x10(%rsp), %rdi
movq %rbp, %rsi
callq 0x6300
cmpq $-0x1, 0xa0(%rsp)
je 0x55dc
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rax
subq %rsi, %rax
pushq $-0x1
popq %rcx
movl %ecx, %r8d
movq 0x38(%rsp), %rdi
movl %edi, %ecx
shll %cl, %r8d
cqto
pushq $0x18
popq %rcx
idivq %rcx
movq %rax, %rdx
pushq $0x1
popq %rax
movl %edi, %ecx
shll %cl, %eax
addl $-0x2, %edx
notl %r8d
movq %r8, 0x60(%rsp)
cltq
decq %rax
movq %rax, 0x58(%rsp)
testl %edx, %edx
js 0x59a1
movl %edx, %eax
imulq $0x18, %rax, %r15
movq 0x20(%rsi,%r15), %r13
cmpq $-0x1, %r13
je 0x5ae7
movq %rbx, %r14
cmpb $0x1, 0x10(%rsi,%r15)
movq %rdx, 0x78(%rsp)
jne 0x578e
movq 0x220(%r14), %rdi
movq %r13, %rsi
callq 0x40a0
movq %rax, %r12
movq (%rsp), %rdi
pushq $0x3
popq %rsi
pushq $0x2
popq %rdx
pushq $0x1
popq %rcx
callq 0xaf6e
movslq %eax, %rbp
leaq (%r12,%rbp), %rax
cmpq $0x1, %rax
jg 0x577e
movq (%rsp), %rdi
pushq $0x3
popq %rsi
pushq $0x2
popq %rdx
pushq $0x1
popq %rcx
callq 0xaf6e
testl %eax, %eax
jne 0x5b63
addq %rbp, %r12
decq %r12
movq 0x38(%rsp), %rcx
shlq %cl, %r12
jmp 0x57fe
addq %r15, %rsi
cmpb $0x1, 0x28(%rsi)
jne 0x57ef
movq 0x220(%r14), %rdi
movq %r13, %rsi
callq 0x40a0
movq %rax, %r12
leaq -0x1(%rax), %rbp
movq 0x58(%rsp), %rax
cmpq %rbp, %rax
cmovlq %rax, %rbp
movq (%rsp), %rdi
pushq $0x3
popq %rsi
pushq $0x2
popq %rdx
pushq $0x1
popq %rcx
callq 0xaf6e
cltq
movq %rbp, %rcx
notq %rcx
addq %rax, %r12
addq %rcx, %r12
testq %r12, %r12
jle 0x5b44
movq 0x38(%rsp), %rcx
shlq %cl, %r12
addq %rbp, %r12
jmp 0x57fe
testl %r13d, 0x60(%rsp)
je 0x5b25
leaq -0x1(%r13), %r12
movq %r14, %rbx
movq 0x220(%r14), %rdi
movq %r12, %rsi
callq 0x40a0
movq %rax, %rbp
movq 0x220(%rbx), %rdi
movq %r13, %rsi
callq 0x40a0
decq %rax
cmpq %rax, %rbp
jne 0x5b06
movq 0x10(%rsp), %rsi
movq %r12, 0x8(%rsi,%r15)
movq 0x78(%rsp), %rdx
decl %edx
movq 0x70(%rsp), %r15
leaq 0x80(%rsp), %r12
movq 0xf79d(%rip), %r13      # 0x14ff0
movq %r14, %rbx
jmp 0x5706
movq (%rsp), %rdi
movq 0x50(%rsp), %rsi
movq 0x40(%rsp), %rdx
movq %r12, %rcx
callq 0x45a0
testl %eax, %eax
jle 0x5bc0
incl 0x228(%rbx)
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x18(%rax)
testb %al, %al
je 0x58ad
movq 0x40(%rsp), %rax
movq (%rax), %rsi
movq (%rsp), %rdi
callq 0x43f0
movq %rax, 0x220(%rbx)
testq %rax, %rax
je 0x5c5b
leaq 0xfb4c(%rip), %rdi      # 0x15400
callq 0x82d6
testb %al, %al
je 0x55dc
movq 0xf708(%rip), %rdi      # 0x14fd0
leaq 0x8b09(%rip), %rsi      # 0xe3d8
callq 0x4340
movq (%rsp), %rcx
movzbl (%rcx), %esi
movq %rax, %rdi
callq 0x4650
movq %rax, %rdi
leaq 0x9280(%rip), %rsi      # 0xeb6d
callq 0x4340
movzbl 0x1b9(%rbx), %esi
movq %rax, %rdi
callq 0x4650
movq %rax, %rdi
leaq 0x9262(%rip), %rsi      # 0xeb6d
callq 0x4340
movzbl 0x1ba(%rbx), %esi
movq %rax, %rdi
callq 0x4650
movq %rax, %rdi
leaq 0x9c99(%rip), %rsi      # 0xf5c2
callq 0x4340
movq 0x80(%rsp), %rcx
movzbl (%rcx), %ecx
xorq $0x80, %rcx
leaq 0x8c76(%rip), %rsi      # 0xe5bd
cmpb $0x2, %cl
ja 0x595a
leaq 0x8f11(%rip), %rdx      # 0xe864
movslq (%rdx,%rcx,4), %rsi
addq %rdx, %rsi
movq %rax, %rdi
callq 0x4340
movq %rax, %rdi
leaq 0x8a75(%rip), %rsi      # 0xe3e1
callq 0x4340
cmpq $0x0, 0x98(%rsp)
leaq 0x8a68(%rip), %rsi      # 0xe3e9
leaq 0x9a62(%rip), %rcx      # 0xf3ea
cmoveq %rcx, %rsi
movq %rax, %rdi
callq 0x4340
movq %rax, %rdi
callq 0x41b0
jmp 0x55dc
movq 0x1a8(%rbx), %rax
cmpq $-0x1, %rax
jne 0x59c6
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rsi
movq %rbx, %rdi
callq 0x6012
movq %rax, 0x1a8(%rbx)
testq %rax, %rax
js 0x5c1d
movq 0x18(%rsp), %rax
movq -0x10(%rax), %rsi
movq %rbx, %rdi
callq 0x6040
movq %rax, 0x1b0(%rbx)
cmpq 0x1a8(%rbx), %rax
jl 0x5c3c
xorl %r14d, %r14d
movl %r14d, %r14d
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rcx
movq %rcx, %rax
subq %rsi, %rax
cqto
pushq $0x18
popq %rdi
idivq %rdi
cmpq %r14, %rax
jbe 0x5a2b
imulq $0x18, %r14, %rax
addq %rax, %rsi
movq %rbx, %rdi
callq 0x6076
incl %r14d
jmp 0x59f7
xorl %r14d, %r14d
movl %r14d, %r14d
movq %rcx, %rax
subq %rsi, %rax
cqto
pushq $0x18
popq %rdi
idivq %rdi
cmpq %r14, %rax
jbe 0x5a6b
imulq $0x18, %r14, %rax
cmpb $0x1, 0x10(%rsi,%rax)
jne 0x5a66
addq %rax, %rsi
movq 0x68(%rsp), %rdi
callq 0x6192
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rcx
incl %r14d
jmp 0x5a2e
movq 0x48(%rsp), %r14
jmp 0x55dc
movq 0x30(%rsp), %rdi
callq 0x46b0
cmpl %eax, 0xc(%rsp)
je 0x5ac9
movq 0xf564(%rip), %rdi      # 0x14ff0
leaq 0x8abc(%rip), %rsi      # 0xe54f
callq 0x4340
movq 0x250(%rbx), %rsi
subq 0x248(%rbx), %rsi
sarq $0x4, %rsi
movq %rax, %rdi
callq 0x4240
leaq 0x8ac6(%rip), %rsi      # 0xe57f
movq %rax, %rdi
callq 0x4340
movq %rax, %rdi
callq 0x41b0
leaq 0x10(%rsp), %rdi
callq 0x5f4a
movb $0x1, %al
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x8971(%rip), %rdi      # 0xe45f
leaq 0x8518(%rip), %rsi      # 0xe00d
leaq 0x8857(%rip), %rcx      # 0xe353
movl $0x126, %edx            # imm = 0x126
callq 0x4210
leaq 0x89c9(%rip), %rdi      # 0xe4d6
leaq 0x84f9(%rip), %rsi      # 0xe00d
leaq 0x8838(%rip), %rcx      # 0xe353
movl $0x14a, %edx            # imm = 0x14A
callq 0x4210
leaq 0x897f(%rip), %rdi      # 0xe4ab
leaq 0x84da(%rip), %rsi      # 0xe00d
leaq 0x8819(%rip), %rcx      # 0xe353
movl $0x144, %edx            # imm = 0x144
callq 0x4210
leaq 0x8954(%rip), %rdi      # 0xe49f
leaq 0x84bb(%rip), %rsi      # 0xe00d
leaq 0x87fa(%rip), %rcx      # 0xe353
movl $0x140, %edx            # imm = 0x140
callq 0x4210
leaq 0x890b(%rip), %rdi      # 0xe475
leaq 0x849c(%rip), %rsi      # 0xe00d
leaq 0x87db(%rip), %rcx      # 0xe353
movl $0x12f, %edx            # imm = 0x12F
callq 0x4210
leaq 0x8799(%rip), %rdi      # 0xe322
leaq 0x847d(%rip), %rsi      # 0xe00d
leaq 0x87bc(%rip), %rcx      # 0xe353
movl $0xdb, %edx
callq 0x4210
leaq 0x845c(%rip), %rdi      # 0xe004
leaq 0x845e(%rip), %rsi      # 0xe00d
leaq 0x879d(%rip), %rcx      # 0xe353
movl $0xe5, %edx
callq 0x4210
leaq 0x87fc(%rip), %rdi      # 0xe3c3
leaq 0x843f(%rip), %rsi      # 0xe00d
leaq 0x877e(%rip), %rcx      # 0xe353
movl $0xf7, %edx
callq 0x4210
leaq 0x8808(%rip), %rdi      # 0xe3ee
leaq 0x8420(%rip), %rsi      # 0xe00d
leaq 0x875f(%rip), %rcx      # 0xe353
movl $0x114, %edx            # imm = 0x114
callq 0x4210
leaq 0x881a(%rip), %rdi      # 0xe41f
leaq 0x8401(%rip), %rsi      # 0xe00d
leaq 0x8740(%rip), %rcx      # 0xe353
movl $0x115, %edx            # imm = 0x115
callq 0x4210
leaq 0x8904(%rip), %rdi      # 0xe528
leaq 0x83e2(%rip), %rsi      # 0xe00d
leaq 0x8721(%rip), %rcx      # 0xe353
movl $0x151, %edx            # imm = 0x151
callq 0x4210
leaq 0x88f5(%rip), %rdi      # 0xe538
leaq 0x83c3(%rip), %rsi      # 0xe00d
leaq 0x8702(%rip), %rcx      # 0xe353
movl $0x153, %edx            # imm = 0x153
callq 0x4210
leaq 0x8769(%rip), %rdi      # 0xe3cb
leaq 0x83a4(%rip), %rsi      # 0xe00d
leaq 0x86e3(%rip), %rcx      # 0xe353
movl $0xff, %edx
callq 0x4210
jmp 0x5c8e
jmp 0x5c8e
jmp 0x5c8e
jmp 0x5c8e
jmp 0x5c8e
jmp 0x5c8e
jmp 0x5c8e
jmp 0x5c8e
jmp 0x5c8e
jmp 0x5c8e
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x5f4a
movq %rbx, %rdi
callq 0x4680
nop