// File: Themaister[P]umusd/ffmpeg.cpp
// Function: FF::decode()
const FF::Buffer& FF::decode()
{
   buffer.clear();
   AVPacket pkt;
   AVFrame frame;
   int got_ptr = 0;
   unsigned retry_cnt = 0;

   while (!got_ptr)
   {
      if (av_read_frame(fctx, &pkt) < 0)
      {
         std::cerr << "av_read_frame() failed." << std::endl;
         return buffer;
      }

      if (pkt.stream_index != aud_stream)
      {
         av_free_packet(&pkt);
         continue;
      }

      if (avcodec_decode_audio4(actx, &frame, &got_ptr, &pkt) < 0)
      {
         std::cerr << "avcodec_decode_audio4() failed." << std::endl;
         av_free_packet(&pkt);

         if (retry_cnt++ < 4)
            continue;

         return buffer;
      }

      av_free_packet(&pkt);
   }

   int size = av_samples_get_buffer_size(nullptr, actx->channels,
         frame.nb_samples, actx->sample_fmt, 1);

   if (pkt.pts != static_cast<std::int64_t>(AV_NOPTS_VALUE))
      last_pos = pkt.pts * av_q2d(fctx->streams[aud_stream]->time_base);

   if (planar_audio)
   {
      std::size_t current_size = buffer.size();
      buffer.resize(buffer.size() + size);
      std::uint8_t* out_ptr = buffer.data() + current_size;

      switch (actx->sample_fmt)
      {
         case AV_SAMPLE_FMT_S16P:
            copy_deplanar<int16_t>(out_ptr, frame.data, frame.nb_samples, actx->channels);
            break;

         case AV_SAMPLE_FMT_S32P:
            copy_deplanar<int32_t>(out_ptr, frame.data, frame.nb_samples, actx->channels);
            break;

         case AV_SAMPLE_FMT_FLTP:
            copy_deplanar<float>(out_ptr, frame.data, frame.nb_samples, actx->channels);
            break;

         default:
            break;
      }
   }
   else
      buffer.insert(buffer.end(), frame.data[0], frame.data[0] + size);

   return buffer;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2f0, %rsp            # imm = 0x2F0
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x2c8(%rbp)
addq $0x88, %rdi
callq 0x17bf0
movl $0x0, -0x284(%rbp)
movl $0x0, -0x288(%rbp)
cmpl $0x0, -0x284(%rbp)
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x175ef
jmp 0x176ea
movq -0x2c8(%rbp), %rax
movq (%rax), %rdi
leaq -0x68(%rbp), %rsi
callq 0x5610
cmpl $0x0, %eax
jge 0x1763f
movq 0x2398a(%rip), %rdi     # 0x3af98
leaq 0xf10d(%rip), %rsi      # 0x26722
callq 0x55d0
movq %rax, %rdi
movq 0x23984(%rip), %rsi     # 0x3afa8
callq 0x5730
movq -0x2c8(%rbp), %rax
addq $0x88, %rax
movq %rax, -0x8(%rbp)
jmp 0x17947
movq -0x2c8(%rbp), %rcx
movl -0x44(%rbp), %eax
cmpl 0x10(%rcx), %eax
je 0x17659
leaq -0x68(%rbp), %rdi
callq 0x5420
jmp 0x175da
movq -0x2c8(%rbp), %rax
movq 0x8(%rax), %rdi
leaq -0x280(%rbp), %rsi
leaq -0x284(%rbp), %rdx
leaq -0x68(%rbp), %rcx
callq 0x5190
cmpl $0x0, %eax
jge 0x176dc
movq 0x23911(%rip), %rdi     # 0x3af98
leaq 0xf0ac(%rip), %rsi      # 0x2673a
callq 0x55d0
movq %rax, %rdi
movq 0x2390b(%rip), %rsi     # 0x3afa8
callq 0x5730
leaq -0x68(%rbp), %rdi
callq 0x5420
movl -0x288(%rbp), %eax
movl %eax, %ecx
addl $0x1, %ecx
movl %ecx, -0x288(%rbp)
cmpl $0x4, %eax
jae 0x176c6
jmp 0x175da
movq -0x2c8(%rbp), %rax
addq $0x88, %rax
movq %rax, -0x8(%rbp)
jmp 0x17947
leaq -0x68(%rbp), %rdi
callq 0x5420
jmp 0x175da
movq -0x2c8(%rbp), %rax
movq 0x8(%rax), %rcx
movl 0x194(%rcx), %esi
movl -0x210(%rbp), %edx
movq 0x8(%rax), %rax
movl 0x198(%rax), %ecx
xorl %eax, %eax
movl %eax, %edi
movl $0x1, %r8d
callq 0x5250
movl %eax, -0x28c(%rbp)
movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000
cmpq %rax, -0x60(%rbp)
je 0x1778a
movq -0x2c8(%rbp), %rcx
cvtsi2sdq -0x60(%rbp), %xmm0
movsd %xmm0, -0x2d0(%rbp)
movq (%rcx), %rax
movq 0x30(%rax), %rax
movslq 0x10(%rcx), %rcx
movq (%rax,%rcx,8), %rax
movq 0x18(%rax), %rax
movq %rax, -0x294(%rbp)
movq -0x294(%rbp), %rdi
callq 0x17580
movq -0x2c8(%rbp), %rax
movaps %xmm0, %xmm1
movsd -0x2d0(%rbp), %xmm0
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x14(%rax)
movq -0x2c8(%rbp), %rax
testb $0x1, 0xa0(%rax)
je 0x178c7
movq -0x2c8(%rbp), %rdi
addq $0x88, %rdi
movq %rdi, -0x2e0(%rbp)
callq 0x6970
movq -0x2e0(%rbp), %rdi
movq %rax, -0x2a0(%rbp)
callq 0x6970
movq -0x2e0(%rbp), %rdi
movq %rax, %rsi
movslq -0x28c(%rbp), %rax
addq %rax, %rsi
callq 0x17c10
movq -0x2e0(%rbp), %rdi
callq 0x17ca0
movq %rax, %rcx
movq -0x2c8(%rbp), %rax
movq -0x2a0(%rbp), %rdx
addq %rdx, %rcx
movq %rcx, -0x2a8(%rbp)
movq 0x8(%rax), %rax
movl 0x198(%rax), %eax
movl %eax, -0x2d4(%rbp)
subl $0x6, %eax
je 0x1783f
jmp 0x17822
movl -0x2d4(%rbp), %eax
subl $0x7, %eax
je 0x1786b
jmp 0x1782f
movl -0x2d4(%rbp), %eax
subl $0x8, %eax
je 0x17897
jmp 0x178c3
movq -0x2c8(%rbp), %rax
movq -0x2a8(%rbp), %rdi
leaq -0x280(%rbp), %rsi
movl -0x210(%rbp), %edx
movq 0x8(%rax), %rax
movl 0x194(%rax), %ecx
callq 0x17cc0
jmp 0x178c5
movq -0x2c8(%rbp), %rax
movq -0x2a8(%rbp), %rdi
leaq -0x280(%rbp), %rsi
movl -0x210(%rbp), %edx
movq 0x8(%rax), %rax
movl 0x194(%rax), %ecx
callq 0x17d50
jmp 0x178c5
movq -0x2c8(%rbp), %rax
movq -0x2a8(%rbp), %rdi
leaq -0x280(%rbp), %rsi
movl -0x210(%rbp), %edx
movq 0x8(%rax), %rax
movl 0x194(%rax), %ecx
callq 0x17de0
jmp 0x178c5
jmp 0x178c5
jmp 0x17936
movq -0x2c8(%rbp), %rdi
movq %rdi, %rax
addq $0x88, %rax
movq %rax, -0x2e8(%rbp)
addq $0x88, %rdi
callq 0x17f10
movq %rax, -0x2b8(%rbp)
leaq -0x2b0(%rbp), %rdi
leaq -0x2b8(%rbp), %rsi
callq 0x17f40
movq -0x2e8(%rbp), %rdi
movq -0x280(%rbp), %rdx
movq -0x280(%rbp), %rcx
movslq -0x28c(%rbp), %rax
addq %rax, %rcx
movq -0x2b0(%rbp), %rsi
callq 0x17e70
movq %rax, -0x2c0(%rbp)
movq -0x2c8(%rbp), %rax
addq $0x88, %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x2f0, %rsp            # imm = 0x2F0
popq %rbp
retq
nopw %cs:(%rax,%rax)