// File: /workspace/github_c_makefile_star2_O0/tvlabs[P]edge264/edge264.c
// Function: edge264_alloc
Edge264Decoder *edge264_alloc(int n_threads, void (*log_cb)(const char *str, void *log_arg), void *log_arg, int log_mbs) {
	Edge264Decoder *dec = calloc(1, sizeof(Edge264Decoder));
	if (dec == NULL)
		return NULL;
	dec->n_threads = n_threads;
	dec->log_cb = log_cb;
	dec->log_arg = log_arg;
	dec->currPic = dec->prevPic = -1;
	dec->taskPics_v = set8(-1);
	
	// select parser functions based on CPU capabilities and logs mode
	#if defined(__SSE2__) // if compiled for Intel
		__builtin_cpu_init();
		if (!__builtin_cpu_supports("cmov") || !__builtin_cpu_supports("sse2"))
			return free(dec), NULL;
	#endif
	dec->worker_loop = ADD_VARIANT(worker_loop);
	dec->parse_nal_unit[1] = dec->parse_nal_unit[5] = ADD_VARIANT(parse_slice_layer_without_partitioning);
	dec->parse_nal_unit[6] = dec->parse_nal_unit[10] = dec->parse_nal_unit[11] = dec->parse_nal_unit[12] = ignore_NAL;
	dec->parse_nal_unit[7] = dec->parse_nal_unit[15] = ADD_VARIANT(parse_seq_parameter_set);
	dec->parse_nal_unit[8] = ADD_VARIANT(parse_pic_parameter_set);
	dec->parse_nal_unit[9] = ADD_VARIANT(parse_access_unit_delimiter);
	dec->parse_nal_unit[14] = dec->parse_nal_unit[20] = ADD_VARIANT(parse_nal_unit_header_extension);
	#ifdef HAS_X86_64_V2
		// macOS's clang does not support x86-64-v3/v2 feature string yet
		if (__builtin_cpu_supports("popcnt") &&
			__builtin_cpu_supports("sse3") &&
			__builtin_cpu_supports("sse4.1") &&
			__builtin_cpu_supports("sse4.2") &&
			__builtin_cpu_supports("ssse3")) {
			dec->worker_loop = worker_loop_v2;
			dec->parse_nal_unit[1] = dec->parse_nal_unit[5] = parse_slice_layer_without_partitioning_v2;
			dec->parse_nal_unit[7] = dec->parse_nal_unit[15] = parse_seq_parameter_set_v2;
			dec->parse_nal_unit[8] = parse_pic_parameter_set_v2;
			dec->parse_nal_unit[9] = parse_access_unit_delimiter_v2;
			dec->parse_nal_unit[14] = dec->parse_nal_unit[20] = parse_nal_unit_header_extension_v2;
		}
	#endif
	#ifdef HAS_X86_64_V3
		if (__builtin_cpu_supports("avx") &&
			__builtin_cpu_supports("avx2") &&
			__builtin_cpu_supports("bmi") &&
			__builtin_cpu_supports("bmi2") &&
			__builtin_cpu_supports("fma")) {
			dec->worker_loop = worker_loop_v3;
			dec->parse_nal_unit[1] = dec->parse_nal_unit[5] = parse_slice_layer_without_partitioning_v3;
			dec->parse_nal_unit[7] = dec->parse_nal_unit[15] = parse_seq_parameter_set_v3;
			dec->parse_nal_unit[8] = parse_pic_parameter_set_v3;
			dec->parse_nal_unit[9] = parse_access_unit_delimiter_v3;
			dec->parse_nal_unit[14] = dec->parse_nal_unit[20] = parse_nal_unit_header_extension_v3;
		}
	#endif
	#ifdef HAS_LOGS
		if (log_cb) {
			dec->parse_nal_unit[1] = dec->parse_nal_unit[5] = parse_slice_layer_without_partitioning_log;
			dec->parse_nal_unit[6] = parse_sei_log;
			dec->parse_nal_unit[7] = dec->parse_nal_unit[15] = parse_seq_parameter_set_log;
			dec->parse_nal_unit[8] = parse_pic_parameter_set_log;
			dec->parse_nal_unit[9] = parse_access_unit_delimiter_log;
			dec->parse_nal_unit[14] = dec->parse_nal_unit[20] = parse_nal_unit_header_extension_log;
			if (log_mbs)
				dec->worker_loop = worker_loop_log;
		}
	#else
		if (log_cb)
			return free(dec), NULL;
	#endif
	
	// get the number of logical cores if requested
	if (n_threads < 0) {
		#ifdef _WIN32
			int n_cpus = atoi(getenv("NUMBER_OF_PROCESSORS"));
		#else
			int n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
		#endif
		n_threads = min(n_cpus, 16);
	}
	
	// if multithreading is disabled we are done, otherwise initialize all
	if (n_threads == 0)
		return dec;
	if (pthread_mutex_init(&dec->lock, NULL) == 0) {
		if (pthread_cond_init(&dec->task_ready, NULL) == 0) {
			if (pthread_cond_init(&dec->task_progress, NULL) == 0) {
				if (pthread_cond_init(&dec->task_complete, NULL) == 0) {
					int i = 0;
					while (i < n_threads && pthread_create(&dec->threads[i], NULL, (void*(*)(void*))dec->worker_loop, dec) == 0)
						i++;
					if (i == n_threads) {
						return dec;
					}
					while (i-- > 0)
						pthread_cancel(dec->threads[i]);
					pthread_cond_destroy(&dec->task_complete);
				}
				pthread_cond_destroy(&dec->task_progress);
			}
			pthread_cond_destroy(&dec->task_ready);
		}
		pthread_mutex_destroy(&dec->lock);
	}
	free(dec);
	return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movl %edi, -0x3c(%rbp)
movq %rsi, -0x48(%rbp)
movq %rdx, -0x50(%rbp)
movl %ecx, -0x54(%rbp)
movl $0x1, %edi
movl $0xa1f0, %esi           # imm = 0xA1F0
callq 0x70b0
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
jne 0x1bdb0
movq $0x0, -0x38(%rbp)
jmp 0x1c27c
movb -0x3c(%rbp), %cl
movq -0x60(%rbp), %rax
movb %cl, 0x20(%rax)
movq -0x48(%rbp), %rcx
movq -0x60(%rbp), %rax
movq %rcx, 0x7c90(%rax)
movq -0x50(%rbp), %rcx
movq -0x60(%rbp), %rax
movq %rcx, 0x7c98(%rax)
movq -0x60(%rbp), %rax
movb $-0x1, 0x25(%rax)
movq -0x60(%rbp), %rax
movb $-0x1, 0x24(%rax)
movb $-0x1, -0x21(%rbp)
movb -0x21(%rbp), %al
movb %al, -0x69(%rbp)
movb %al, -0x1(%rbp)
movb %al, -0x2(%rbp)
movb %al, -0x3(%rbp)
movb %al, -0x4(%rbp)
movb %al, -0x5(%rbp)
movb %al, -0x6(%rbp)
movb %al, -0x7(%rbp)
movb %al, -0x8(%rbp)
movb %al, -0x9(%rbp)
movb %al, -0xa(%rbp)
movb %al, -0xb(%rbp)
movb %al, -0xc(%rbp)
movb %al, -0xd(%rbp)
movb %al, -0xe(%rbp)
movb %al, -0xf(%rbp)
movb %al, -0x10(%rbp)
movzbl -0x10(%rbp), %eax
vmovd %eax, %xmm0
movzbl -0xf(%rbp), %eax
vpinsrb $0x1, %eax, %xmm0, %xmm0
movzbl -0xe(%rbp), %eax
vpinsrb $0x2, %eax, %xmm0, %xmm0
movzbl -0xd(%rbp), %eax
vpinsrb $0x3, %eax, %xmm0, %xmm0
movzbl -0xc(%rbp), %eax
vpinsrb $0x4, %eax, %xmm0, %xmm0
movzbl -0xb(%rbp), %eax
vpinsrb $0x5, %eax, %xmm0, %xmm0
movzbl -0xa(%rbp), %eax
vpinsrb $0x6, %eax, %xmm0, %xmm0
movzbl -0x9(%rbp), %eax
vpinsrb $0x7, %eax, %xmm0, %xmm0
movzbl -0x8(%rbp), %eax
vpinsrb $0x8, %eax, %xmm0, %xmm0
movzbl -0x7(%rbp), %eax
vpinsrb $0x9, %eax, %xmm0, %xmm0
movzbl -0x6(%rbp), %eax
vpinsrb $0xa, %eax, %xmm0, %xmm0
movzbl -0x5(%rbp), %eax
vpinsrb $0xb, %eax, %xmm0, %xmm0
movzbl -0x4(%rbp), %eax
vpinsrb $0xc, %eax, %xmm0, %xmm0
movzbl -0x3(%rbp), %eax
vpinsrb $0xd, %eax, %xmm0, %xmm0
movzbl -0x2(%rbp), %eax
vpinsrb $0xe, %eax, %xmm0, %xmm0
movzbl -0x1(%rbp), %eax
vpinsrb $0xf, %eax, %xmm0, %xmm0
vmovdqa %xmm0, -0x20(%rbp)
vmovdqa -0x20(%rbp), %xmm0
movq -0x60(%rbp), %rax
vmovdqa %xmm0, 0x1780(%rax)
callq 0x71b0
movl 0xbb61b(%rip), %eax     # 0xd74fc
andl $0x1, %eax
cmpl $0x1, %eax
sete %al
andb $0x1, %al
testb $0x1, %al
jne 0x1bef2
jmp 0x1bf07
movl 0xbb604(%rip), %eax     # 0xd74fc
andl $0x10, %eax
cmpl $0x10, %eax
sete %al
andb $0x1, %al
testb $0x1, %al
jne 0x1bf1d
movq -0x60(%rbp), %rdi
callq 0x7030
movq $0x0, -0x38(%rbp)
jmp 0x1c27c
movq -0x60(%rbp), %rax
movq 0xbb090(%rip), %rcx     # 0xd6fb8
movq %rcx, 0x170(%rax)
movq -0x60(%rbp), %rax
movq 0xbb05e(%rip), %rcx     # 0xd6f98
movq %rcx, 0x2a0(%rax)
movq -0x60(%rbp), %rax
movq 0xbb04c(%rip), %rcx     # 0xd6f98
movq %rcx, 0x280(%rax)
movq -0x60(%rbp), %rax
leaq 0x332(%rip), %rcx       # 0x1c290
movq %rcx, 0x2d8(%rax)
movq -0x60(%rbp), %rax
leaq 0x320(%rip), %rcx       # 0x1c290
movq %rcx, 0x2d0(%rax)
movq -0x60(%rbp), %rax
leaq 0x30e(%rip), %rcx       # 0x1c290
movq %rcx, 0x2c8(%rax)
movq -0x60(%rbp), %rax
leaq 0x2fc(%rip), %rcx       # 0x1c290
movq %rcx, 0x2a8(%rax)
movq -0x60(%rbp), %rax
movq 0xbb01a(%rip), %rcx     # 0xd6fc0
movq %rcx, 0x2f0(%rax)
movq -0x60(%rbp), %rax
movq 0xbb008(%rip), %rcx     # 0xd6fc0
movq %rcx, 0x2b0(%rax)
movq -0x60(%rbp), %rax
movq 0xbafe6(%rip), %rcx     # 0xd6fb0
movq %rcx, 0x2b8(%rax)
movq -0x60(%rbp), %rax
movq 0xbb00c(%rip), %rcx     # 0xd6fe8
movq %rcx, 0x2c0(%rax)
movq -0x60(%rbp), %rax
movq 0xbafe2(%rip), %rcx     # 0xd6fd0
movq %rcx, 0x318(%rax)
movq -0x60(%rbp), %rax
movq 0xbafd0(%rip), %rcx     # 0xd6fd0
movq %rcx, 0x2e8(%rax)
cmpq $0x0, -0x48(%rbp)
je 0x1c0ce
movq -0x60(%rbp), %rax
movq 0xbaf8b(%rip), %rcx     # 0xd6fa8
movq %rcx, 0x2a0(%rax)
movq -0x60(%rbp), %rax
movq 0xbaf79(%rip), %rcx     # 0xd6fa8
movq %rcx, 0x280(%rax)
movq -0x60(%rbp), %rax
movq 0xbaf3f(%rip), %rcx     # 0xd6f80
movq %rcx, 0x2a8(%rax)
movq -0x60(%rbp), %rax
movq 0xbaf35(%rip), %rcx     # 0xd6f88
movq %rcx, 0x2f0(%rax)
movq -0x60(%rbp), %rax
movq 0xbaf23(%rip), %rcx     # 0xd6f88
movq %rcx, 0x2b0(%rax)
movq -0x60(%rbp), %rax
movq 0xbaf51(%rip), %rcx     # 0xd6fc8
movq %rcx, 0x2b8(%rax)
movq -0x60(%rbp), %rax
movq 0xbaee7(%rip), %rcx     # 0xd6f70
movq %rcx, 0x2c0(%rax)
movq -0x60(%rbp), %rax
movq 0xbaf3d(%rip), %rcx     # 0xd6fd8
movq %rcx, 0x318(%rax)
movq -0x60(%rbp), %rax
movq 0xbaf2b(%rip), %rcx     # 0xd6fd8
movq %rcx, 0x2e8(%rax)
cmpl $0x0, -0x54(%rbp)
je 0x1c0cc
movq -0x60(%rbp), %rax
movq 0xbaedb(%rip), %rcx     # 0xd6fa0
movq %rcx, 0x170(%rax)
jmp 0x1c0ce
cmpl $0x0, -0x3c(%rbp)
jge 0x1c10a
movl $0x54, %edi
callq 0x7120
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %eax
movl %eax, -0x28(%rbp)
movl $0x10, -0x2c(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jge 0x1c0fe
movl -0x28(%rbp), %eax
movl %eax, -0x70(%rbp)
jmp 0x1c104
movl -0x2c(%rbp), %eax
movl %eax, -0x70(%rbp)
movl -0x70(%rbp), %eax
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jne 0x1c11d
movq -0x60(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x1c27c
movq -0x60(%rbp), %rdi
addq $0x1580, %rdi           # imm = 0x1580
xorl %eax, %eax
movl %eax, %esi
callq 0x7140
cmpl $0x0, %eax
jne 0x1c26b
movq -0x60(%rbp), %rdi
addq $0x15a8, %rdi           # imm = 0x15A8
xorl %eax, %eax
movl %eax, %esi
callq 0x70d0
cmpl $0x0, %eax
jne 0x1c25b
movq -0x60(%rbp), %rdi
addq $0x15d8, %rdi           # imm = 0x15D8
xorl %eax, %eax
movl %eax, %esi
callq 0x70d0
cmpl $0x0, %eax
jne 0x1c24b
movq -0x60(%rbp), %rdi
addq $0x1608, %rdi           # imm = 0x1608
xorl %eax, %eax
movl %eax, %esi
callq 0x70d0
cmpl $0x0, %eax
jne 0x1c23b
movl $0x0, -0x68(%rbp)
movl -0x68(%rbp), %ecx
xorl %eax, %eax
cmpl -0x3c(%rbp), %ecx
movb %al, -0x71(%rbp)
jge 0x1c1dc
movq -0x60(%rbp), %rdi
addq $0x1500, %rdi           # imm = 0x1500
movslq -0x68(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x60(%rbp), %rax
movq 0x170(%rax), %rdx
movq -0x60(%rbp), %rcx
xorl %eax, %eax
movl %eax, %esi
callq 0x7100
cmpl $0x0, %eax
sete %al
movb %al, -0x71(%rbp)
movb -0x71(%rbp), %al
testb $0x1, %al
jne 0x1c1e5
jmp 0x1c1f0
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x1c198
movl -0x68(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jne 0x1c202
movq -0x60(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x1c27c
jmp 0x1c204
movl -0x68(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x68(%rbp)
cmpl $0x0, %eax
jle 0x1c22b
movq -0x60(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq 0x1500(%rax,%rcx,8), %rdi
callq 0x7130
jmp 0x1c204
movq -0x60(%rbp), %rdi
addq $0x1608, %rdi           # imm = 0x1608
callq 0x7110
movq -0x60(%rbp), %rdi
addq $0x15d8, %rdi           # imm = 0x15D8
callq 0x7110
movq -0x60(%rbp), %rdi
addq $0x15a8, %rdi           # imm = 0x15A8
callq 0x7110
movq -0x60(%rbp), %rdi
addq $0x1580, %rdi           # imm = 0x1580
callq 0x7060
movq -0x60(%rbp), %rdi
callq 0x7030
movq $0x0, -0x38(%rbp)
movq -0x38(%rbp), %rax
addq $0x80, %rsp
popq %rbp
retq
nopl (%rax)