FreeRDP
dsp_ffmpeg.c
1 
21 #include <freerdp/config.h>
22 
23 #include <freerdp/log.h>
24 
25 #include <libavcodec/avcodec.h>
26 #include <libavutil/avutil.h>
27 #include <libavutil/opt.h>
28 #if defined(SWRESAMPLE_FOUND)
29 #include <libswresample/swresample.h>
30 #elif defined(AVRESAMPLE_FOUND)
31 #include <libavresample/avresample.h>
32 #else
33 #error "libswresample or libavresample required"
34 #endif
35 
36 #include "dsp.h"
37 #include "dsp_ffmpeg.h"
38 
39 #define TAG FREERDP_TAG("dsp.ffmpeg")
40 
41 struct S_FREERDP_DSP_CONTEXT
42 {
44 
45  BOOL isOpen;
46 
47  UINT32 bufferedSamples;
48 
49  enum AVCodecID id;
50  const AVCodec* codec;
51  AVCodecContext* context;
52  AVFrame* frame;
53  AVFrame* resampled;
54  AVFrame* buffered;
55  AVPacket* packet;
56 #if defined(SWRESAMPLE_FOUND)
57  SwrContext* rcontext;
58 #else
59  AVAudioResampleContext* rcontext;
60 #endif
61 };
62 
63 static BOOL ffmpeg_codec_is_filtered(enum AVCodecID id, BOOL encoder)
64 {
65  switch (id)
66  {
67 #if !defined(WITH_DSP_EXPERIMENTAL)
68 
69  case AV_CODEC_ID_ADPCM_IMA_OKI:
70  case AV_CODEC_ID_MP3:
71  case AV_CODEC_ID_ADPCM_MS:
72  case AV_CODEC_ID_G723_1:
73  case AV_CODEC_ID_GSM_MS:
74  case AV_CODEC_ID_PCM_ALAW:
75  case AV_CODEC_ID_PCM_MULAW:
76  return TRUE;
77 #endif
78 
79  case AV_CODEC_ID_NONE:
80  return TRUE;
81 
82  case AV_CODEC_ID_AAC:
83  case AV_CODEC_ID_AAC_LATM:
84  return FALSE;
85 
86  default:
87  return FALSE;
88  }
89 }
90 
91 static enum AVCodecID ffmpeg_get_avcodec(const AUDIO_FORMAT* WINPR_RESTRICT format)
92 {
93  if (!format)
94  return AV_CODEC_ID_NONE;
95 
96  switch (format->wFormatTag)
97  {
98  case WAVE_FORMAT_UNKNOWN:
99  return AV_CODEC_ID_NONE;
100 
101  case WAVE_FORMAT_PCM:
102  switch (format->wBitsPerSample)
103  {
104  case 16:
105  return AV_CODEC_ID_PCM_U16LE;
106 
107  case 8:
108  return AV_CODEC_ID_PCM_U8;
109 
110  default:
111  return AV_CODEC_ID_NONE;
112  }
113 
114  case WAVE_FORMAT_DVI_ADPCM:
115  return AV_CODEC_ID_ADPCM_IMA_OKI;
116 
117  case WAVE_FORMAT_ADPCM:
118  return AV_CODEC_ID_ADPCM_MS;
119 
120  case WAVE_FORMAT_ALAW:
121  return AV_CODEC_ID_PCM_ALAW;
122 
123  case WAVE_FORMAT_MULAW:
124  return AV_CODEC_ID_PCM_MULAW;
125 
126  case WAVE_FORMAT_GSM610:
127  return AV_CODEC_ID_GSM_MS;
128 
129  case WAVE_FORMAT_MSG723:
130  return AV_CODEC_ID_G723_1;
131 
132  case WAVE_FORMAT_AAC_MS:
133  return AV_CODEC_ID_AAC;
134 
135  case WAVE_FORMAT_OPUS:
136  return AV_CODEC_ID_OPUS;
137 
138  default:
139  return AV_CODEC_ID_NONE;
140  }
141 }
142 
143 static int ffmpeg_sample_format(const AUDIO_FORMAT* WINPR_RESTRICT format)
144 {
145  switch (format->wFormatTag)
146  {
147  case WAVE_FORMAT_PCM:
148  switch (format->wBitsPerSample)
149  {
150  case 8:
151  return AV_SAMPLE_FMT_U8;
152 
153  case 16:
154  return AV_SAMPLE_FMT_S16;
155 
156  default:
157  return FALSE;
158  }
159 
160  case WAVE_FORMAT_DVI_ADPCM:
161  case WAVE_FORMAT_ADPCM:
162  return AV_SAMPLE_FMT_S16P;
163 
164  case WAVE_FORMAT_MPEGLAYER3:
165  case WAVE_FORMAT_AAC_MS:
166  return AV_SAMPLE_FMT_FLTP;
167 
168  case WAVE_FORMAT_OPUS:
169  return AV_SAMPLE_FMT_S16;
170 
171  case WAVE_FORMAT_MSG723:
172  case WAVE_FORMAT_GSM610:
173  return AV_SAMPLE_FMT_S16P;
174 
175  case WAVE_FORMAT_ALAW:
176  return AV_SAMPLE_FMT_S16;
177 
178  default:
179  return FALSE;
180  }
181 }
182 
183 static void ffmpeg_close_context(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
184 {
185  if (context)
186  {
187  if (context->context)
188  avcodec_free_context(&context->context);
189 
190  if (context->frame)
191  av_frame_free(&context->frame);
192 
193  if (context->resampled)
194  av_frame_free(&context->resampled);
195 
196  if (context->buffered)
197  av_frame_free(&context->buffered);
198 
199  if (context->packet)
200  av_packet_free(&context->packet);
201 
202  if (context->rcontext)
203  {
204 #if defined(SWRESAMPLE_FOUND)
205  swr_free(&context->rcontext);
206 #else
207  avresample_free(&context->rcontext);
208 #endif
209  }
210 
211  context->id = AV_CODEC_ID_NONE;
212  context->codec = NULL;
213  context->isOpen = FALSE;
214  context->context = NULL;
215  context->frame = NULL;
216  context->resampled = NULL;
217  context->packet = NULL;
218  context->rcontext = NULL;
219  }
220 }
221 
222 static BOOL ffmpeg_open_context(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
223 {
224  int ret = 0;
225 
226  if (!context || context->isOpen)
227  return FALSE;
228 
229  const AUDIO_FORMAT* format = &context->common.format;
230 
231  if (!format)
232  return FALSE;
233  context->id = ffmpeg_get_avcodec(format);
234 
235  if (ffmpeg_codec_is_filtered(context->id, context->common.encoder))
236  goto fail;
237 
238  if (context->common.encoder)
239  context->codec = avcodec_find_encoder(context->id);
240  else
241  context->codec = avcodec_find_decoder(context->id);
242 
243  if (!context->codec)
244  goto fail;
245 
246  context->context = avcodec_alloc_context3(context->codec);
247 
248  if (!context->context)
249  goto fail;
250 
251  switch (context->id)
252  {
253  /* We need support for multichannel and sample rates != 8000 */
254  case AV_CODEC_ID_GSM_MS:
255  context->context->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
256  break;
257 
258  case AV_CODEC_ID_AAC:
259  context->context->profile = FF_PROFILE_AAC_MAIN;
260  break;
261 
262  default:
263  break;
264  }
265 
266  context->context->max_b_frames = 1;
267  context->context->delay = 0;
268 
269 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
270  av_channel_layout_default(&context->context->ch_layout, format->nChannels);
271 #else
272  context->context->channels = format->nChannels;
273  const int64_t layout = av_get_default_channel_layout(format->nChannels);
274  context->context->channel_layout = layout;
275 #endif
276  context->context->sample_rate = (int)format->nSamplesPerSec;
277  context->context->block_align = format->nBlockAlign;
278  context->context->bit_rate = format->nAvgBytesPerSec * 8LL;
279  context->context->sample_fmt = ffmpeg_sample_format(format);
280  context->context->time_base = av_make_q(1, context->context->sample_rate);
281 
282  if ((ret = avcodec_open2(context->context, context->codec, NULL)) < 0)
283  {
284  const char* err = av_err2str(ret);
285  WLog_ERR(TAG, "Error avcodec_open2 %s [%d]", err, ret);
286  goto fail;
287  }
288 
289  context->packet = av_packet_alloc();
290 
291  if (!context->packet)
292  goto fail;
293 
294  context->frame = av_frame_alloc();
295 
296  if (!context->frame)
297  goto fail;
298 
299  context->resampled = av_frame_alloc();
300 
301  if (!context->resampled)
302  goto fail;
303 
304  context->buffered = av_frame_alloc();
305 
306  if (!context->buffered)
307  goto fail;
308 
309 #if defined(SWRESAMPLE_FOUND)
310  context->rcontext = swr_alloc();
311 #else
312  context->rcontext = avresample_alloc_context();
313 #endif
314 
315  if (!context->rcontext)
316  goto fail;
317 
318 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
319  av_channel_layout_default(&context->frame->ch_layout, format->nChannels);
320 #else
321  context->frame->channel_layout = layout;
322  context->frame->channels = format->nChannels;
323 #endif
324  WINPR_ASSERT(format->nSamplesPerSec <= INT_MAX);
325  context->frame->sample_rate = (int)format->nSamplesPerSec;
326  context->frame->format = AV_SAMPLE_FMT_S16;
327 
328  if (context->common.encoder)
329  {
330  context->resampled->format = context->context->sample_fmt;
331  context->resampled->sample_rate = context->context->sample_rate;
332  }
333  else
334  {
335  context->resampled->format = AV_SAMPLE_FMT_S16;
336 
337  WINPR_ASSERT(format->nSamplesPerSec <= INT_MAX);
338  context->resampled->sample_rate = (int)format->nSamplesPerSec;
339  }
340 
341 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
342  av_channel_layout_default(&context->resampled->ch_layout, format->nChannels);
343 #else
344  context->resampled->channel_layout = layout;
345  context->resampled->channels = format->nChannels;
346 #endif
347 
348  if (context->context->frame_size > 0)
349  {
350 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
351  ret = av_channel_layout_copy(&context->buffered->ch_layout, &context->resampled->ch_layout);
352  if (ret != 0)
353  goto fail;
354 #else
355  context->buffered->channel_layout = context->resampled->channel_layout;
356  context->buffered->channels = context->resampled->channels;
357 #endif
358  context->buffered->format = context->resampled->format;
359  context->buffered->nb_samples = context->context->frame_size;
360 
361  ret = av_frame_get_buffer(context->buffered, 1);
362  if (ret < 0)
363  goto fail;
364  }
365 
366  context->isOpen = TRUE;
367  return TRUE;
368 fail:
369  ffmpeg_close_context(context);
370  return FALSE;
371 }
372 
373 #if defined(SWRESAMPLE_FOUND)
374 static BOOL ffmpeg_resample_frame(SwrContext* WINPR_RESTRICT context, AVFrame* WINPR_RESTRICT in,
375  AVFrame* WINPR_RESTRICT out)
376 {
377  int ret = 0;
378 
379  if (!swr_is_initialized(context))
380  {
381  if ((ret = swr_config_frame(context, out, in)) < 0)
382  {
383  const char* err = av_err2str(ret);
384  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
385  return FALSE;
386  }
387 
388  if ((ret = (swr_init(context))) < 0)
389  {
390  const char* err = av_err2str(ret);
391  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
392  return FALSE;
393  }
394  }
395 
396  if ((ret = swr_convert_frame(context, out, in)) < 0)
397  {
398  const char* err = av_err2str(ret);
399  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
400  return FALSE;
401  }
402 
403  return TRUE;
404 }
405 #else
406 static BOOL ffmpeg_resample_frame(AVAudioResampleContext* WINPR_RESTRICT context,
407  AVFrame* WINPR_RESTRICT in, AVFrame* WINPR_RESTRICT out)
408 {
409  int ret;
410 
411  if (!avresample_is_open(context))
412  {
413  if ((ret = avresample_config(context, out, in)) < 0)
414  {
415  const char* err = av_err2str(ret);
416  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
417  return FALSE;
418  }
419 
420  if ((ret = (avresample_open(context))) < 0)
421  {
422  const char* err = av_err2str(ret);
423  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
424  return FALSE;
425  }
426  }
427 
428  if ((ret = avresample_convert_frame(context, out, in)) < 0)
429  {
430  const char* err = av_err2str(ret);
431  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
432  return FALSE;
433  }
434 
435  return TRUE;
436 }
437 #endif
438 
439 static BOOL ffmpeg_encode_frame(AVCodecContext* WINPR_RESTRICT context, AVFrame* WINPR_RESTRICT in,
440  AVPacket* WINPR_RESTRICT packet, wStream* WINPR_RESTRICT out)
441 {
442  if (in->format == AV_SAMPLE_FMT_FLTP)
443  {
444  uint8_t** pp = in->extended_data;
445 #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 28, 100)
446  const int nr_channels = in->channels;
447 #else
448  const int nr_channels = in->ch_layout.nb_channels;
449 #endif
450 
451  for (int y = 0; y < nr_channels; y++)
452  {
453  float* data = (float*)pp[y];
454  for (int x = 0; x < in->nb_samples; x++)
455  {
456  const float val1 = data[x];
457  if (isnan(val1))
458  data[x] = 0.0f;
459  else if (isinf(val1))
460  {
461  if (val1 < 0.0f)
462  data[x] = -1.0f;
463  else
464  data[x] = 1.0f;
465  }
466  }
467  }
468  }
469  /* send the packet with the compressed data to the encoder */
470  int ret = avcodec_send_frame(context, in);
471 
472  if (ret < 0)
473  {
474  const char* err = av_err2str(ret);
475  WLog_ERR(TAG, "Error submitting the packet to the encoder %s [%d]", err, ret);
476  return FALSE;
477  }
478 
479  /* read all the output frames (in general there may be any number of them */
480  while (TRUE)
481  {
482  ret = avcodec_receive_packet(context, packet);
483 
484  if ((ret == AVERROR(EAGAIN)) || (ret == AVERROR_EOF))
485  break;
486 
487  if (ret < 0)
488  {
489  const char* err = av_err2str(ret);
490  WLog_ERR(TAG, "Error during encoding %s [%d]", err, ret);
491  return FALSE;
492  }
493 
494  WINPR_ASSERT(packet->size >= 0);
495  if (!Stream_EnsureRemainingCapacity(out, (size_t)packet->size))
496  return FALSE;
497 
498  Stream_Write(out, packet->data, (size_t)packet->size);
499  av_packet_unref(packet);
500  }
501 
502  return TRUE;
503 }
504 
505 static BOOL ffmpeg_fill_frame(AVFrame* WINPR_RESTRICT frame,
506  const AUDIO_FORMAT* WINPR_RESTRICT inputFormat,
507  const BYTE* WINPR_RESTRICT data, size_t size)
508 {
509  int ret = 0;
510 #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 28, 100)
511  frame->channels = inputFormat->nChannels;
512  frame->channel_layout = av_get_default_channel_layout(frame->channels);
513 #else
514  av_channel_layout_default(&frame->ch_layout, inputFormat->nChannels);
515 #endif
516  WINPR_ASSERT(inputFormat->nSamplesPerSec <= INT_MAX);
517  frame->sample_rate = (int)inputFormat->nSamplesPerSec;
518  frame->format = ffmpeg_sample_format(inputFormat);
519 
520  const int bpp = av_get_bytes_per_sample(frame->format);
521  WINPR_ASSERT(bpp >= 0);
522  WINPR_ASSERT(size <= INT_MAX);
523  const size_t nb_samples = size / inputFormat->nChannels / (size_t)bpp;
524  frame->nb_samples = (int)nb_samples;
525 
526  if ((ret = avcodec_fill_audio_frame(frame, inputFormat->nChannels, frame->format, data,
527  (int)size, 1)) < 0)
528  {
529  const char* err = av_err2str(ret);
530  WLog_ERR(TAG, "Error during audio frame fill %s [%d]", err, ret);
531  return FALSE;
532  }
533 
534  return TRUE;
535 }
536 #if defined(SWRESAMPLE_FOUND)
537 static BOOL ffmpeg_decode(AVCodecContext* WINPR_RESTRICT dec_ctx, AVPacket* WINPR_RESTRICT pkt,
538  AVFrame* WINPR_RESTRICT frame, SwrContext* WINPR_RESTRICT resampleContext,
539  AVFrame* WINPR_RESTRICT resampled, wStream* WINPR_RESTRICT out)
540 #else
541 static BOOL ffmpeg_decode(AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame,
542  AVAudioResampleContext* resampleContext, AVFrame* resampled, wStream* out)
543 #endif
544 {
545  int ret = 0;
546  /* send the packet with the compressed data to the decoder */
547  ret = avcodec_send_packet(dec_ctx, pkt);
548 
549  if (ret < 0)
550  {
551  const char* err = av_err2str(ret);
552  WLog_ERR(TAG, "Error submitting the packet to the decoder %s [%d]", err, ret);
553  return FALSE;
554  }
555 
556  /* read all the output frames (in general there may be any number of them */
557  while (ret >= 0)
558  {
559  ret = avcodec_receive_frame(dec_ctx, frame);
560 
561  if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
562  return TRUE;
563  else if (ret < 0)
564  {
565  const char* err = av_err2str(ret);
566  WLog_ERR(TAG, "Error during decoding %s [%d]", err, ret);
567  return FALSE;
568  }
569 
570 #if defined(SWRESAMPLE_FOUND)
571  if (!swr_is_initialized(resampleContext))
572  {
573  if ((ret = swr_config_frame(resampleContext, resampled, frame)) < 0)
574  {
575 #else
576  if (!avresample_is_open(resampleContext))
577  {
578  if ((ret = avresample_config(resampleContext, resampled, frame)) < 0)
579  {
580 #endif
581  const char* err = av_err2str(ret);
582  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
583  return FALSE;
584  }
585 
586 #if defined(SWRESAMPLE_FOUND)
587  if ((ret = (swr_init(resampleContext))) < 0)
588 #else
589  if ((ret = (avresample_open(resampleContext))) < 0)
590 #endif
591  {
592  const char* err = av_err2str(ret);
593  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
594  return FALSE;
595  }
596  }
597 
598 #if defined(SWRESAMPLE_FOUND)
599  if ((ret = swr_convert_frame(resampleContext, resampled, frame)) < 0)
600 #else
601  if ((ret = avresample_convert_frame(resampleContext, resampled, frame)) < 0)
602 #endif
603  {
604  const char* err = av_err2str(ret);
605  WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
606  return FALSE;
607  }
608 
609  {
610 
611 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
612  WINPR_ASSERT(resampled->ch_layout.nb_channels >= 0);
613  const size_t nrchannels = (size_t)resampled->ch_layout.nb_channels;
614 #else
615  const size_t nrchannels = resampled->channels;
616 #endif
617  WINPR_ASSERT(resampled->nb_samples >= 0);
618  const size_t data_size = nrchannels * (size_t)resampled->nb_samples * 2ull;
619  if (!Stream_EnsureRemainingCapacity(out, data_size))
620  return FALSE;
621  Stream_Write(out, resampled->data[0], data_size);
622  }
623  }
624 
625  return TRUE;
626 }
627 
628 BOOL freerdp_dsp_ffmpeg_supports_format(const AUDIO_FORMAT* WINPR_RESTRICT format, BOOL encode)
629 {
630  enum AVCodecID id = ffmpeg_get_avcodec(format);
631 
632  if (ffmpeg_codec_is_filtered(id, encode))
633  return FALSE;
634 
635  if (encode)
636  return avcodec_find_encoder(id) != NULL;
637  else
638  return avcodec_find_decoder(id) != NULL;
639 }
640 
641 FREERDP_DSP_CONTEXT* freerdp_dsp_ffmpeg_context_new(BOOL encode)
642 {
643  FREERDP_DSP_CONTEXT* context = NULL;
644 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
645  avcodec_register_all();
646 #endif
647  context = calloc(1, sizeof(FREERDP_DSP_CONTEXT));
648 
649  if (!context)
650  goto fail;
651 
652  if (!freerdp_dsp_common_context_init(&context->common, encode))
653  goto fail;
654 
655  return context;
656 
657 fail:
658  WINPR_PRAGMA_DIAG_PUSH
659  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
660  freerdp_dsp_ffmpeg_context_free(context);
661  WINPR_PRAGMA_DIAG_POP
662  return NULL;
663 }
664 
665 void freerdp_dsp_ffmpeg_context_free(FREERDP_DSP_CONTEXT* context)
666 {
667  if (context)
668  {
669  ffmpeg_close_context(context);
670  freerdp_dsp_common_context_uninit(&context->common);
671  free(context);
672  }
673 }
674 
675 BOOL freerdp_dsp_ffmpeg_context_reset(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
676  const AUDIO_FORMAT* WINPR_RESTRICT targetFormat)
677 {
678  if (!context || !targetFormat)
679  return FALSE;
680 
681  ffmpeg_close_context(context);
682  context->common.format = *targetFormat;
683  return ffmpeg_open_context(context);
684 }
685 
686 static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
687  const BYTE* WINPR_RESTRICT src, size_t size,
688  const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
689  const BYTE** WINPR_RESTRICT data, size_t* WINPR_RESTRICT length,
690  AUDIO_FORMAT* WINPR_RESTRICT dstFormat)
691 {
692  UINT32 bpp = 0;
693  size_t samples = 0;
694 
695  if (!context || !data || !length || !dstFormat)
696  return FALSE;
697 
698  if (srcFormat->wFormatTag != WAVE_FORMAT_PCM)
699  return FALSE;
700 
701  bpp = srcFormat->wBitsPerSample > 8 ? 2 : 1;
702  samples = size / bpp / srcFormat->nChannels;
703 
704  *dstFormat = *srcFormat;
705  if (context->common.format.nChannels == srcFormat->nChannels)
706  {
707  *data = src;
708  *length = size;
709  return TRUE;
710  }
711 
712  Stream_SetPosition(context->common.channelmix, 0);
713 
714  /* Destination has more channels than source */
715  if (context->common.format.nChannels > srcFormat->nChannels)
716  {
717  switch (srcFormat->nChannels)
718  {
719  case 1:
720  if (!Stream_EnsureCapacity(context->common.channelmix, size * 2))
721  return FALSE;
722 
723  for (size_t x = 0; x < samples; x++)
724  {
725  for (size_t y = 0; y < bpp; y++)
726  Stream_Write_UINT8(context->common.channelmix, src[x * bpp + y]);
727 
728  for (size_t y = 0; y < bpp; y++)
729  Stream_Write_UINT8(context->common.channelmix, src[x * bpp + y]);
730  }
731 
732  Stream_SealLength(context->common.channelmix);
733  *data = Stream_Buffer(context->common.channelmix);
734  *length = Stream_Length(context->common.channelmix);
735  dstFormat->nChannels = 2;
736  return TRUE;
737 
738  case 2: /* We only support stereo, so we can not handle this case. */
739  default: /* Unsupported number of channels */
740  WLog_WARN(TAG, "[%s] unsuported source channel count %" PRIu16, __func__,
741  srcFormat->nChannels);
742  return FALSE;
743  }
744  }
745 
746  /* Destination has less channels than source */
747  switch (srcFormat->nChannels)
748  {
749  case 2:
750  if (!Stream_EnsureCapacity(context->common.channelmix, size / 2))
751  return FALSE;
752 
753  /* Simply drop second channel.
754  * TODO: Calculate average */
755  for (size_t x = 0; x < samples; x++)
756  {
757  for (size_t y = 0; y < bpp; y++)
758  Stream_Write_UINT8(context->common.channelmix, src[2 * x * bpp + y]);
759  }
760 
761  Stream_SealLength(context->common.channelmix);
762  *data = Stream_Buffer(context->common.channelmix);
763  *length = Stream_Length(context->common.channelmix);
764  dstFormat->nChannels = 1;
765  return TRUE;
766 
767  case 1: /* Invalid, do we want to use a 0 channel sound? */
768  default: /* Unsupported number of channels */
769  WLog_WARN(TAG, "[%s] unsuported channel count %" PRIu16, __func__,
770  srcFormat->nChannels);
771  return FALSE;
772  }
773 
774  return FALSE;
775 }
776 
777 BOOL freerdp_dsp_ffmpeg_encode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
778  const AUDIO_FORMAT* WINPR_RESTRICT format,
779  const BYTE* WINPR_RESTRICT sdata, size_t length,
780  wStream* WINPR_RESTRICT out)
781 {
782  AUDIO_FORMAT fmt = { 0 };
783 
784  if (!context || !format || !sdata || !out || !context->common.encoder)
785  return FALSE;
786 
787  if (!context || !sdata || !out)
788  return FALSE;
789 
790  /* https://github.com/FreeRDP/FreeRDP/issues/7607
791  *
792  * we get noisy data with channel transformation, so do it ourselves.
793  */
794  const BYTE* data = NULL;
795  if (!freerdp_dsp_channel_mix(context, sdata, length, format, &data, &length, &fmt))
796  return FALSE;
797 
798  /* Create input frame */
799  if (!ffmpeg_fill_frame(context->frame, format, data, length))
800  return FALSE;
801 
802  /* Resample to desired format. */
803  if (!ffmpeg_resample_frame(context->rcontext, context->frame, context->resampled))
804  return FALSE;
805 
806  if (context->context->frame_size <= 0)
807  {
808  return ffmpeg_encode_frame(context->context, context->resampled, context->packet, out);
809  }
810  else
811  {
812  int copied = 0;
813  int rest = context->resampled->nb_samples;
814 
815  do
816  {
817  int inSamples = rest;
818 
819  if ((inSamples < 0) || (context->bufferedSamples > (UINT32)(INT_MAX - inSamples)))
820  return FALSE;
821 
822  if (inSamples + (int)context->bufferedSamples > context->context->frame_size)
823  inSamples = context->context->frame_size - (int)context->bufferedSamples;
824 
825 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
826  const int nrchannels = context->context->ch_layout.nb_channels;
827 #else
828  const int nrchannels = context->context->channels;
829 #endif
830  const int rc =
831  av_samples_copy(context->buffered->extended_data, context->resampled->extended_data,
832  (int)context->bufferedSamples, copied, inSamples, nrchannels,
833  context->context->sample_fmt);
834  if (rc < 0)
835  return FALSE;
836  rest -= inSamples;
837  copied += inSamples;
838  context->bufferedSamples += (UINT32)inSamples;
839 
840  if (context->context->frame_size <= (int)context->bufferedSamples)
841  {
842  /* Encode in desired format. */
843  if (!ffmpeg_encode_frame(context->context, context->buffered, context->packet, out))
844  return FALSE;
845 
846  context->bufferedSamples = 0;
847  }
848  } while (rest > 0);
849 
850  return TRUE;
851  }
852 }
853 
854 BOOL freerdp_dsp_ffmpeg_decode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
855  const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
856  const BYTE* WINPR_RESTRICT data, size_t length,
857  wStream* WINPR_RESTRICT out)
858 {
859  if (!context || !srcFormat || !data || !out || context->common.encoder)
860  return FALSE;
861 
862 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
863  av_init_packet(context->packet);
864 #endif
865  context->packet->data = WINPR_CAST_CONST_PTR_AWAY(data, uint8_t*);
866 
867  WINPR_ASSERT(length <= INT_MAX);
868  context->packet->size = (int)length;
869  return ffmpeg_decode(context->context, context->packet, context->frame, context->rcontext,
870  context->resampled, out);
871 }