// File: cpearce[P]OggIndex/src/Decoder.cpp
// Function: VorbisDecoder::Decode(ogg_page*, long)
bool Decode(ogg_page* page, ogg_int64_t offset) {
    if (GotAllHeaders()) {
      // Reset the vorbis syntheis. This simulates what happens when we seek
      // to this page and start decoding with no prior knowledge. This forces
      // the decoder to preroll again.
      ogg_stream_reset(&mState);
      vorbis_synthesis_restart(&mDsp);
    }

    ogg_packet packet;
    assert(ogg_stream_packetout(&mState, &packet) == 0);
    int ret = ogg_stream_pagein(&mState, page);
    assert(ret == 0);
    int total_samples = 0;
    ogg_int64_t start_time = -1;

    while ((ret = ogg_stream_packetout(&mState, &packet)) == 1) {

      if (!GotAllHeaders()) {
        ogg_int32_t ret = vorbis_synthesis_headerin(&mInfo, &mComment, &packet);
        if (ret == 0) {
          mHeadersRead++;
        }
        if (gOptions.GetDumpPackets()) {
          cout << "[V] ver="
               << (int)mInfo.version << " "
               << VorbisHeaderType(&packet) << " packet"
               << (packet.e_o_s ? " eos" : "")
               << endl;
        }
        if (GotAllHeaders()) {
          ret = vorbis_synthesis_init(&mDsp, &mInfo);
          assert(ret == 0);
          ret = vorbis_block_init(&mDsp, &mBlock);
          assert(ret == 0);
        }
        continue;
      }
      assert(GotAllHeaders());

      // Decode page, get start and end time.
      // We only expect the last packet in a page to have non -1 granulepos.
      assert(start_time == -1);
      int samples = 0;
      
      // Decode the vorbis to determine how many samples are in each packet.
      if (vorbis_synthesis(&mBlock, &packet) == 0) {
        ret = vorbis_synthesis_blockin(&mDsp, &mBlock);
        assert(ret == 0);
      }
      while ((samples = vorbis_synthesis_pcmout(&mDsp, 0)) > 0) {
        total_samples += samples;
        ret = vorbis_synthesis_read(&mDsp, samples);
        assert(ret == 0);
      }

      if (packet.granulepos != -1) {
        assert(packet.granulepos == ogg_page_granulepos(page));
        ogg_int64_t start_granule = packet.granulepos - total_samples;
        start_time = Time(start_granule);
        if (!mGotFirstContentPage && start_time < 0) {
          // The first content page may specify fewer samples in its granulepos
          // than are actually in the the first page. As per the vorbis spec,
          // these should not be played, so we exclude them here.
          start_time = 0;
        }
        ogg_int64_t end_time = Time(packet.granulepos);

        mGotFirstContentPage = true;


        // First packet will be included in the index, the cut off threshold
        // is then set relative to that.

        if (gOptions.GetDumpKeyPackets() || gOptions.GetDumpPackets()) {
          cout << "[V] sample time_ms=[" << start_time << "," << end_time
               << "] granulepos=[" << start_granule << ","
               << packet.granulepos << "]"
               << (packet.e_o_s ? " eos" : "")
               << endl;
        }    

        assert(start_time >= 0);
        if (start_time > mNextKeyframeThreshold) {
          mKeyFrames.push_back(KeyFrameInfo(offset, start_time));
          mNextKeyframeThreshold = Time(ogg_page_granulepos(page)) +
                                   gOptions.GetKeyPointInterval();
        }
        assert(ogg_stream_packetout(&mState, &packet) == 0);
        
        if (mStartTime == -1) {
          mStartTime = start_time;
        }
        mEndTime = end_time;

      }
    } // while packetout

    return true;
  }

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0xa0(%rsp)
movq %rsi, 0x98(%rsp)
movq %rdx, 0x90(%rsp)
movq 0xa0(%rsp), %rdi
movq %rdi, 0x20(%rsp)
movq (%rdi), %rax
callq *0x18(%rax)
testb $0x1, %al
jne 0xaff8
jmp 0xb017
movq 0x20(%rsp), %rdi
addq $0x8, %rdi
callq 0x53f0
movq 0x20(%rsp), %rdi
addq $0x238, %rdi            # imm = 0x238
callq 0x5610
movq 0x20(%rsp), %rdi
addq $0x8, %rdi
leaq 0x60(%rsp), %rsi
callq 0x5680
cmpl $0x0, %eax
jne 0xb031
jmp 0xb050
leaq 0x126b9(%rip), %rdi     # 0x1d6f1
leaq 0x11fce(%rip), %rsi     # 0x1d00d
movl $0x1be, %edx            # imm = 0x1BE
leaq 0x126d2(%rip), %rcx     # 0x1d71d
callq 0x5280
movq 0x20(%rsp), %rdi
addq $0x8, %rdi
movq 0x98(%rsp), %rsi
callq 0x5620
movl %eax, 0x5c(%rsp)
cmpl $0x0, 0x5c(%rsp)
jne 0xb073
jmp 0xb092
leaq 0x11f8a(%rip), %rdi     # 0x1d004
leaq 0x11f8c(%rip), %rsi     # 0x1d00d
movl $0x1c0, %edx            # imm = 0x1C0
leaq 0x12690(%rip), %rcx     # 0x1d71d
callq 0x5280
movl $0x0, 0x58(%rsp)
movq $-0x1, 0x50(%rsp)
movq 0x20(%rsp), %rdi
addq $0x8, %rdi
leaq 0x60(%rsp), %rsi
callq 0x5680
movl %eax, 0x5c(%rsp)
cmpl $0x1, %eax
jne 0xb668
movq 0x20(%rsp), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
testb $0x1, %al
jne 0xb26a
movq 0x20(%rsp), %rsi
movq %rsi, %rdi
addq $0x1e0, %rdi            # imm = 0x1E0
addq $0x218, %rsi            # imm = 0x218
leaq 0x60(%rsp), %rdx
callq 0x5130
movl %eax, 0x4c(%rsp)
cmpl $0x0, 0x4c(%rsp)
jne 0xb115
movq 0x20(%rsp), %rax
movl 0x1dc(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x1dc(%rax)
leaq 0x1d3c4(%rip), %rdi     # 0x284e0
callq 0x10970
testb $0x1, %al
jne 0xb12a
jmp 0xb1c1
movq 0x1ce9f(%rip), %rdi     # 0x27fd0
leaq 0x12621(%rip), %rsi     # 0x1d759
callq 0x53d0
movq %rax, %rdi
movq 0x20(%rsp), %rax
movl 0x1e0(%rax), %esi
callq 0x57a0
movq %rax, %rdi
leaq 0x1344a(%rip), %rsi     # 0x1e5a4
callq 0x53d0
movq 0x20(%rsp), %rdi
movq %rax, 0x18(%rsp)
leaq 0x60(%rsp), %rsi
callq 0xb820
movq 0x18(%rsp), %rdi
movq %rax, %rsi
callq 0x53d0
movq %rax, %rdi
leaq 0x12257(%rip), %rsi     # 0x1d3e1
callq 0x53d0
movq %rax, %rdi
movq 0x78(%rsp), %rcx
leaq 0x1322e(%rip), %rsi     # 0x1e3cc
leaq 0x12244(%rip), %rax     # 0x1d3e9
cmpq $0x0, %rcx
cmovneq %rax, %rsi
callq 0x53d0
movq %rax, %rdi
movq 0x1ce04(%rip), %rsi     # 0x27fc0
callq 0x5430
movq 0x20(%rsp), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
testb $0x1, %al
jne 0xb1d5
jmp 0xb265
movq 0x20(%rsp), %rsi
movq %rsi, %rdi
addq $0x238, %rdi            # imm = 0x238
addq $0x1e0, %rsi            # imm = 0x1E0
callq 0x5390
movl %eax, 0x4c(%rsp)
cmpl $0x0, 0x4c(%rsp)
jne 0xb1fd
jmp 0xb21c
leaq 0x11e00(%rip), %rdi     # 0x1d004
leaq 0x11e02(%rip), %rsi     # 0x1d00d
movl $0x1d4, %edx            # imm = 0x1D4
leaq 0x12506(%rip), %rcx     # 0x1d71d
callq 0x5280
movq 0x20(%rsp), %rsi
movq %rsi, %rdi
addq $0x238, %rdi            # imm = 0x238
addq $0x2c8, %rsi            # imm = 0x2C8
callq 0x55a0
movl %eax, 0x4c(%rsp)
cmpl $0x0, 0x4c(%rsp)
jne 0xb244
jmp 0xb263
leaq 0x11db9(%rip), %rdi     # 0x1d004
leaq 0x11dbb(%rip), %rsi     # 0x1d00d
movl $0x1d6, %edx            # imm = 0x1D6
leaq 0x124bf(%rip), %rcx     # 0x1d71d
callq 0x5280
jmp 0xb265
jmp 0xb0a3
movq 0x20(%rsp), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
testb $0x1, %al
jne 0xb27b
jmp 0xb27d
jmp 0xb29c
leaq 0x124de(%rip), %rdi     # 0x1d762
leaq 0x11d82(%rip), %rsi     # 0x1d00d
movl $0x1da, %edx            # imm = 0x1DA
leaq 0x12486(%rip), %rcx     # 0x1d71d
callq 0x5280
cmpq $-0x1, 0x50(%rsp)
jne 0xb2a6
jmp 0xb2c5
leaq 0x124c5(%rip), %rdi     # 0x1d772
leaq 0x11d59(%rip), %rsi     # 0x1d00d
movl $0x1de, %edx            # imm = 0x1DE
leaq 0x1245d(%rip), %rcx     # 0x1d71d
callq 0x5280
movq 0x20(%rsp), %rdi
movl $0x0, 0x48(%rsp)
addq $0x2c8, %rdi            # imm = 0x2C8
leaq 0x60(%rsp), %rsi
callq 0x5220
cmpl $0x0, %eax
jne 0xb331
movq 0x20(%rsp), %rsi
movq %rsi, %rdi
addq $0x238, %rdi            # imm = 0x238
addq $0x2c8, %rsi            # imm = 0x2C8
callq 0x5330
movl %eax, 0x5c(%rsp)
cmpl $0x0, 0x5c(%rsp)
jne 0xb310
jmp 0xb32f
leaq 0x11ced(%rip), %rdi     # 0x1d004
leaq 0x11cef(%rip), %rsi     # 0x1d00d
movl $0x1e4, %edx            # imm = 0x1E4
leaq 0x123f3(%rip), %rcx     # 0x1d71d
callq 0x5280
jmp 0xb331
jmp 0xb333
movq 0x20(%rsp), %rdi
addq $0x238, %rdi            # imm = 0x238
xorl %eax, %eax
movl %eax, %esi
callq 0x54b0
movl %eax, 0x48(%rsp)
cmpl $0x0, %eax
jle 0xb3a0
movq 0x20(%rsp), %rdi
movl 0x48(%rsp), %eax
addl 0x58(%rsp), %eax
movl %eax, 0x58(%rsp)
addq $0x238, %rdi            # imm = 0x238
movl 0x48(%rsp), %esi
callq 0x5640
movl %eax, 0x5c(%rsp)
cmpl $0x0, 0x5c(%rsp)
jne 0xb37f
jmp 0xb39e
leaq 0x11c7e(%rip), %rdi     # 0x1d004
leaq 0x11c80(%rip), %rsi     # 0x1d00d
movl $0x1e9, %edx            # imm = 0x1E9
leaq 0x12384(%rip), %rcx     # 0x1d71d
callq 0x5280
jmp 0xb333
cmpq $-0x1, 0x80(%rsp)
je 0xb663
movq 0x80(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x98(%rsp), %rdi
callq 0x56e0
movq %rax, %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
jne 0xb3d8
jmp 0xb3f7
leaq 0x123a4(%rip), %rdi     # 0x1d783
leaq 0x11c27(%rip), %rsi     # 0x1d00d
movl $0x1ed, %edx            # imm = 0x1ED
leaq 0x1232b(%rip), %rcx     # 0x1d71d
callq 0x5280
movq 0x20(%rsp), %rdi
movq 0x80(%rsp), %rax
movslq 0x58(%rsp), %rcx
subq %rcx, %rax
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rsi
callq 0xb8a0
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x50(%rsp)
testb $0x1, 0x1d8(%rax)
jne 0xb442
cmpq $0x0, 0x50(%rsp)
jge 0xb442
movq $0x0, 0x50(%rsp)
movq 0x20(%rsp), %rdi
movq 0x80(%rsp), %rsi
callq 0xb8a0
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x38(%rsp)
movb $0x1, 0x1d8(%rax)
leaq 0x1d071(%rip), %rdi     # 0x284e0
callq 0xa360
testb $0x1, %al
jne 0xb48d
leaq 0x1d061(%rip), %rdi     # 0x284e0
callq 0x10970
testb $0x1, %al
jne 0xb48d
jmp 0xb545
movq 0x1cb3c(%rip), %rdi     # 0x27fd0
leaq 0x12317(%rip), %rsi     # 0x1d7b2
callq 0x53d0
movq %rax, %rdi
movq 0x50(%rsp), %rsi
callq 0x5810
movq %rax, %rdi
leaq 0x12c09(%rip), %rsi     # 0x1e0c0
callq 0x53d0
movq %rax, %rdi
movq 0x38(%rsp), %rsi
callq 0x5810
movq %rax, %rdi
leaq 0x122f4(%rip), %rsi     # 0x1d7c7
callq 0x53d0
movq %rax, %rdi
movq 0x40(%rsp), %rsi
callq 0x5810
movq %rax, %rdi
leaq 0x12bd1(%rip), %rsi     # 0x1e0c0
callq 0x53d0
movq %rax, %rdi
movq 0x80(%rsp), %rsi
callq 0x5810
movq %rax, %rdi
leaq 0x11c7d(%rip), %rsi     # 0x1d18b
callq 0x53d0
movq %rax, %rdi
movq 0x78(%rsp), %rcx
leaq 0x12eaa(%rip), %rsi     # 0x1e3cc
leaq 0x11ec0(%rip), %rax     # 0x1d3e9
cmpq $0x0, %rcx
cmovneq %rax, %rsi
callq 0x53d0
movq %rax, %rdi
movq 0x1ca80(%rip), %rsi     # 0x27fc0
callq 0x5430
cmpq $0x0, 0x50(%rsp)
jl 0xb54f
jmp 0xb56e
leaq 0x12280(%rip), %rdi     # 0x1d7d6
leaq 0x11ab0(%rip), %rsi     # 0x1d00d
movl $0x206, %edx            # imm = 0x206
leaq 0x121b4(%rip), %rcx     # 0x1d71d
callq 0x5280
movq 0x20(%rsp), %rcx
movq 0x50(%rsp), %rax
cmpq 0x1b8(%rcx), %rax
jle 0xb5f9
movq 0x20(%rsp), %rax
addq $0x1c0, %rax            # imm = 0x1C0
movq %rax, (%rsp)
movq 0x90(%rsp), %rsi
movq 0x50(%rsp), %rdx
leaq 0x28(%rsp), %rdi
callq 0x6de0
movq (%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x6db0
movq 0x98(%rsp), %rdi
callq 0x56e0
movq 0x20(%rsp), %rdi
movq %rax, %rsi
callq 0xb8a0
movq %rax, 0x8(%rsp)
leaq 0x1cf05(%rip), %rdi     # 0x284e0
callq 0xa5d0
movq 0x8(%rsp), %rcx
movl %eax, %edx
movq 0x20(%rsp), %rax
movslq %edx, %rdx
addq %rdx, %rcx
movq %rcx, 0x1b8(%rax)
movq 0x20(%rsp), %rdi
addq $0x8, %rdi
leaq 0x60(%rsp), %rsi
callq 0x5680
cmpl $0x0, %eax
jne 0xb613
jmp 0xb632
leaq 0x120d7(%rip), %rdi     # 0x1d6f1
leaq 0x119ec(%rip), %rsi     # 0x1d00d
movl $0x20c, %edx            # imm = 0x20C
leaq 0x120f0(%rip), %rcx     # 0x1d71d
callq 0x5280
movq 0x20(%rsp), %rax
cmpq $-0x1, 0x1a8(%rax)
jne 0xb652
movq 0x20(%rsp), %rax
movq 0x50(%rsp), %rcx
movq %rcx, 0x1a8(%rax)
movq 0x20(%rsp), %rax
movq 0x38(%rsp), %rcx
movq %rcx, 0x1b0(%rax)
jmp 0xb0a3
movb $0x1, %al
andb $0x1, %al
addq $0xa8, %rsp
retq
nopw %cs:(%rax,%rax)
nop