Загрузка данных


static void *pa_thread_hnd_out(void *arg) {
	struct pa_strm *pa_stream = (struct pa_strm *) arg;
	int err;
	struct audio_dev *audio_dev;
	uint8_t *out_buf = NULL;
	int inp_frames;
	int buf_len;
	int div;

	audio_dev = audio_dev_get_by_idx(pa_stream->devid);
	if(!audio_dev || !audio_dev->ad_ops || !audio_dev->ad_ops->ad_ops_start || !audio_dev->ad_ops->ad_ops_resume) {
		printf("pa_thread_hnd: failed audio_dev=%p\n",audio_dev);
		return NULL;
	}
	
	buf_len = audio_dev->ad_ops->ad_ops_ioctl(audio_dev, ADIOCTL_BUFLEN, NULL);
	if (buf_len == -1) {
		printf("Couldn't get audio device buf_len\n");
		return NULL;
	}
	if (!pa_stream->callback) {
		printf("No callback provided for PA thread.\n");
		return NULL;
	}
	
	pa_cond_wait(pa_stream);
	audio_dev->ad_ops->ad_ops_start(audio_dev);

	// inp_frames — это строго то количество фреймов, которое просит PJSIP (например, 320 моно фреймов)
	inp_frames = pa_stream->frames_per_buffer; 
	
	int audio_dev_rate = audio_dev->ad_ops->ad_ops_ioctl(audio_dev, ADIOCTL_GET_RATE, NULL);
	div = audio_dev_rate / pa_stream->rate;
	if(div <= 0) div = 1;

	printf("pa_thread_hnd_out) Active codec framesPerBuffer=%d, hardware buf_len=%d\n", inp_frames, buf_len);

	while (1) {
		pa_cond_wait(pa_stream);
		if (pa_stream->state != PA_STREAM_RUNNING) {
			printf("Exit pa_out_thread\n");
			audio_dev_close_out_stream();
			return NULL;
		}
		
		if (audio_dev->dir == AUDIO_DEV_OUTPUT) {
			out_buf = audio_dev_get_out_cur_ptr(audio_dev);
			memset(out_buf, 0, buf_len);
		}
		
		// Передаем в callback ИМЕННО inp_frames. PJSIP заполнит ровно inp_frames сэмплов (320 сэмплов = 640 байт моно)
		err = pa_stream->callback(NULL, out_buf, inp_frames, NULL, 0, pa_stream->user_data);
		
		switch (err) {
			case paContinue: break;
			case paComplete: Pa_StopStream(pa_stream); break;
			default:
				printf("pa_thread_hnd_out: User callback error: %d\n", err);
				Pa_StopStream(pa_stream);
				break;
		}
		
		if (audio_dev->dir == AUDIO_DEV_OUTPUT) {
			// ВАЖНО: Разворачиваем in-place из моно (320) в стерео (320 фреймов = 640 сэмплов = 1280 байт)
			pa_do_channel_conversion(pa_stream, audio_dev, out_buf, inp_frames);
			
			// Затем делаем ресемплинг, если частоты железа и стрима не совпадают
			pa_do_rate_conversion(pa_stream, audio_dev, out_buf, inp_frames * div);
		}
		
		pa_stream->active = 0;
		audio_dev->ad_ops->ad_ops_resume(audio_dev);
	}
	audio_dev_close_out_stream();
	return NULL;
}