FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
tsmf_ffmpeg.c
1
20#include <freerdp/config.h>
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <winpr/crt.h>
27
28#include <freerdp/channels/log.h>
29#include <freerdp/client/tsmf.h>
30
31#include <libavcodec/avcodec.h>
32#include <libavutil/common.h>
33#include <libavutil/cpu.h>
34#include <libavutil/imgutils.h>
35
36#include "tsmf_constants.h"
37#include "tsmf_decoder.h"
38#include "tsmf_audio.h"
39
40/* Compatibility with older FFmpeg */
41#if LIBAVUTIL_VERSION_MAJOR < 50
42#define AVMEDIA_TYPE_VIDEO 0
43#define AVMEDIA_TYPE_AUDIO 1
44#endif
45
46#if LIBAVCODEC_VERSION_MAJOR < 54
47#define MAX_AUDIO_FRAME_SIZE AVCODEC_MAX_AUDIO_FRAME_SIZE
48#else
49#define MAX_AUDIO_FRAME_SIZE 192000
50#endif
51
52#if LIBAVCODEC_VERSION_MAJOR < 55
53#define AV_CODEC_ID_VC1 CODEC_ID_VC1
54#define AV_CODEC_ID_WMAV2 CODEC_ID_WMAV2
55#define AV_CODEC_ID_WMAPRO CODEC_ID_WMAPRO
56#define AV_CODEC_ID_MP3 CODEC_ID_MP3
57#define AV_CODEC_ID_MP2 CODEC_ID_MP2
58#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
59#define AV_CODEC_ID_WMV3 CODEC_ID_WMV3
60#define AV_CODEC_ID_AAC CODEC_ID_AAC
61#define AV_CODEC_ID_H264 CODEC_ID_H264
62#define AV_CODEC_ID_AC3 CODEC_ID_AC3
63#endif
64
65#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2)
66#define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED
67#define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED
68#endif
69
70#if LIBAVUTIL_VERSION_MAJOR < 52
71#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
72#endif
73
74typedef struct
75{
76 ITSMFDecoder iface;
77
78 int media_type;
79#if LIBAVCODEC_VERSION_MAJOR < 55
80 enum CodecID codec_id;
81#else
82 enum AVCodecID codec_id;
83#endif
84 AVCodecContext* codec_context;
85 const AVCodec* codec;
86 AVFrame* frame;
87 int prepared;
88
89 BYTE* decoded_data;
90 UINT32 decoded_size;
91 UINT32 decoded_size_max;
92} TSMFFFmpegDecoder;
93
94static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder* decoder)
95{
96 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
97 mdecoder->codec_context = avcodec_alloc_context3(NULL);
98
99 if (!mdecoder->codec_context)
100 {
101 WLog_ERR(TAG, "avcodec_alloc_context failed.");
102 return FALSE;
103 }
104
105 return TRUE;
106}
107
108static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
109{
110 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
111 mdecoder->codec_context->width = media_type->Width;
112 mdecoder->codec_context->height = media_type->Height;
113 mdecoder->codec_context->bit_rate = media_type->BitRate;
114 mdecoder->codec_context->time_base.den = media_type->SamplesPerSecond.Numerator;
115 mdecoder->codec_context->time_base.num = media_type->SamplesPerSecond.Denominator;
116#if LIBAVCODEC_VERSION_MAJOR < 55
117 mdecoder->frame = avcodec_alloc_frame();
118#else
119 mdecoder->frame = av_frame_alloc();
120#endif
121 return TRUE;
122}
123
124static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
125{
126 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
127 mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator;
128 mdecoder->codec_context->bit_rate = media_type->BitRate;
129#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
130 mdecoder->codec_context->ch_layout.nb_channels = media_type->Channels;
131#else
132 mdecoder->codec_context->channels = media_type->Channels;
133#endif
134 mdecoder->codec_context->block_align = media_type->BlockAlign;
135#if LIBAVCODEC_VERSION_MAJOR < 55
136#ifdef AV_CPU_FLAG_SSE2
137 mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2;
138#else
139#if LIBAVCODEC_VERSION_MAJOR < 53
140 mdecoder->codec_context->dsp_mask = FF_MM_SSE2 | FF_MM_MMXEXT;
141#else
142 mdecoder->codec_context->dsp_mask = FF_MM_SSE2 | FF_MM_MMX2;
143#endif
144#endif
145#else /* LIBAVCODEC_VERSION_MAJOR < 55 */
146#ifdef AV_CPU_FLAG_SSE2
147#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 17, 100)
148 av_set_cpu_flags_mask(AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMXEXT);
149#else
150 av_force_cpu_flags(AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMXEXT);
151#endif
152#else
153 av_set_cpu_flags_mask(FF_MM_SSE2 | FF_MM_MMX2);
154#endif
155#endif /* LIBAVCODEC_VERSION_MAJOR < 55 */
156 return TRUE;
157}
158
159static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
160{
161 BYTE* p = NULL;
162 UINT32 size = 0;
163 const BYTE* s = NULL;
164 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
165
166 WINPR_PRAGMA_DIAG_PUSH
167 WINPR_PRAGMA_DIAG_IGNORED_QUALIFIERS
168 mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
169 WINPR_PRAGMA_DIAG_POP
170
171 if (!mdecoder->codec)
172 {
173 WLog_ERR(TAG, "avcodec_find_decoder failed.");
174 return FALSE;
175 }
176
177 mdecoder->codec_context->codec_id = mdecoder->codec_id;
178 mdecoder->codec_context->codec_type = mdecoder->media_type;
179
180 switch (mdecoder->media_type)
181 {
182 case AVMEDIA_TYPE_VIDEO:
183 if (!tsmf_ffmpeg_init_video_stream(decoder, media_type))
184 return FALSE;
185
186 break;
187
188 case AVMEDIA_TYPE_AUDIO:
189 if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
190 return FALSE;
191
192 break;
193
194 default:
195 WLog_ERR(TAG, "unknown media_type %d", mdecoder->media_type);
196 break;
197 }
198
199 if (media_type->ExtraData)
200 {
201 /* Add a padding to avoid invalid memory read in some codec */
202 mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8;
203 mdecoder->codec_context->extradata = calloc(1, mdecoder->codec_context->extradata_size);
204
205 if (!mdecoder->codec_context->extradata)
206 return FALSE;
207
208 if (media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
209 media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
210 {
211 size_t required = 6;
212 /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska.
213 See http://haali.su/mkv/codecs.pdf */
214 p = mdecoder->codec_context->extradata;
215 if ((mdecoder->codec_context->extradata_size < 0) ||
216 ((size_t)mdecoder->codec_context->extradata_size < required))
217 return FALSE;
218 *p++ = 1; /* Reserved? */
219 *p++ = media_type->ExtraData[8]; /* Profile */
220 *p++ = 0; /* Profile */
221 *p++ = media_type->ExtraData[12]; /* Level */
222 *p++ = 0xff; /* Flag? */
223 *p++ = 0xe0 | 0x01; /* Reserved | #sps */
224 s = media_type->ExtraData + 20;
225 size = ((UINT32)(*s)) * 256 + ((UINT32)(*(s + 1)));
226 required += size + 2;
227 if ((mdecoder->codec_context->extradata_size < 0) ||
228 ((size_t)mdecoder->codec_context->extradata_size < required))
229 return FALSE;
230 memcpy(p, s, size + 2);
231 s += size + 2;
232 p += size + 2;
233 required++;
234 if ((mdecoder->codec_context->extradata_size < 0) ||
235 ((size_t)mdecoder->codec_context->extradata_size < required))
236 return FALSE;
237 *p++ = 1; /* #pps */
238 size = ((UINT32)(*s)) * 256 + ((UINT32)(*(s + 1)));
239 required += size + 2;
240 if ((mdecoder->codec_context->extradata_size < 0) ||
241 ((size_t)mdecoder->codec_context->extradata_size < required))
242 return FALSE;
243 memcpy(p, s, size + 2);
244 }
245 else
246 {
247 memcpy(mdecoder->codec_context->extradata, media_type->ExtraData,
248 media_type->ExtraDataSize);
249 if ((mdecoder->codec_context->extradata_size < 0) ||
250 ((size_t)mdecoder->codec_context->extradata_size <
251 media_type->ExtraDataSize + 8ull))
252 return FALSE;
253 memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8);
254 }
255 }
256
257#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100)
258 if (mdecoder->codec->capabilities & AV_CODEC_CAP_TRUNCATED)
259 mdecoder->codec_context->flags |= AV_CODEC_FLAG_TRUNCATED;
260#endif
261
262 return TRUE;
263}
264
265static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder* decoder)
266{
267 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
268
269 if (avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
270 {
271 WLog_ERR(TAG, "avcodec_open2 failed.");
272 return FALSE;
273 }
274
275 mdecoder->prepared = 1;
276 return TRUE;
277}
278
279static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type)
280{
281 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
282
283 WINPR_ASSERT(mdecoder);
284 WINPR_ASSERT(media_type);
285
286 switch (media_type->MajorType)
287 {
288 case TSMF_MAJOR_TYPE_VIDEO:
289 mdecoder->media_type = AVMEDIA_TYPE_VIDEO;
290 break;
291
292 case TSMF_MAJOR_TYPE_AUDIO:
293 mdecoder->media_type = AVMEDIA_TYPE_AUDIO;
294 break;
295
296 default:
297 return FALSE;
298 }
299
300 switch (media_type->SubType)
301 {
302 case TSMF_SUB_TYPE_WVC1:
303 mdecoder->codec_id = AV_CODEC_ID_VC1;
304 break;
305
306 case TSMF_SUB_TYPE_WMA2:
307 mdecoder->codec_id = AV_CODEC_ID_WMAV2;
308 break;
309
310 case TSMF_SUB_TYPE_WMA9:
311 mdecoder->codec_id = AV_CODEC_ID_WMAPRO;
312 break;
313
314 case TSMF_SUB_TYPE_MP3:
315 mdecoder->codec_id = AV_CODEC_ID_MP3;
316 break;
317
318 case TSMF_SUB_TYPE_MP2A:
319 mdecoder->codec_id = AV_CODEC_ID_MP2;
320 break;
321
322 case TSMF_SUB_TYPE_MP2V:
323 mdecoder->codec_id = AV_CODEC_ID_MPEG2VIDEO;
324 break;
325
326 case TSMF_SUB_TYPE_WMV3:
327 mdecoder->codec_id = AV_CODEC_ID_WMV3;
328 break;
329
330 case TSMF_SUB_TYPE_AAC:
331 mdecoder->codec_id = AV_CODEC_ID_AAC;
332
333 /* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data
334 is at the end of it. See
335 http://msdn.microsoft.com/en-us/library/dd757806.aspx */
336 if (media_type->ExtraData)
337 {
338 if (media_type->ExtraDataSize < 12)
339 return FALSE;
340
341 media_type->ExtraData += 12;
342 media_type->ExtraDataSize -= 12;
343 }
344
345 break;
346
347 case TSMF_SUB_TYPE_H264:
348 case TSMF_SUB_TYPE_AVC1:
349 mdecoder->codec_id = AV_CODEC_ID_H264;
350 break;
351
352 case TSMF_SUB_TYPE_AC3:
353 mdecoder->codec_id = AV_CODEC_ID_AC3;
354 break;
355
356 default:
357 return FALSE;
358 }
359
360 if (!tsmf_ffmpeg_init_context(decoder))
361 return FALSE;
362
363 if (!tsmf_ffmpeg_init_stream(decoder, media_type))
364 return FALSE;
365
366 if (!tsmf_ffmpeg_prepare(decoder))
367 return FALSE;
368
369 return TRUE;
370}
371
372static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size,
373 UINT32 extensions)
374{
375 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
376 int decoded = 0;
377 int len = 0;
378 AVFrame* frame = NULL;
379 BOOL ret = TRUE;
380#if LIBAVCODEC_VERSION_MAJOR < 52 || \
381 (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
382 len = avcodec_decode_video(mdecoder->codec_context, mdecoder->frame, &decoded, data, data_size);
383#else
384 {
385 AVPacket pkt = { 0 };
386#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
387 av_init_packet(&pkt);
388#endif
389 pkt.data = WINPR_CAST_CONST_PTR_AWAY(data, BYTE*);
390 pkt.size = data_size;
391
392 if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
393 pkt.flags |= AV_PKT_FLAG_KEY;
394
395#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
396 len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt);
397#else
398 len = avcodec_send_packet(mdecoder->codec_context, &pkt);
399 if (len > 0)
400 {
401 len = avcodec_receive_frame(mdecoder->codec_context, mdecoder->frame);
402 if (len == AVERROR(EAGAIN))
403 return TRUE;
404 }
405#endif
406 }
407#endif
408
409 if (len < 0)
410 {
411 WLog_ERR(TAG, "data_size %" PRIu32 ", avcodec_decode_video failed (%d)", data_size, len);
412 ret = FALSE;
413 }
414 else if (!decoded)
415 {
416 WLog_ERR(TAG, "data_size %" PRIu32 ", no frame is decoded.", data_size);
417 ret = FALSE;
418 }
419 else
420 {
421 DEBUG_TSMF("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d "
422 "pix_fmt %d width %d height %d",
423 mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
424 mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
425 mdecoder->codec_context->pix_fmt, mdecoder->codec_context->width,
426 mdecoder->codec_context->height);
427 mdecoder->decoded_size = av_image_get_buffer_size(mdecoder->codec_context->pix_fmt,
428 mdecoder->codec_context->width,
429 mdecoder->codec_context->height, 1);
430 mdecoder->decoded_data = calloc(1, mdecoder->decoded_size);
431
432 if (!mdecoder->decoded_data)
433 return FALSE;
434
435#if LIBAVCODEC_VERSION_MAJOR < 55
436 frame = avcodec_alloc_frame();
437#else
438 frame = av_frame_alloc();
439#endif
440 av_image_fill_arrays(frame->data, frame->linesize, mdecoder->decoded_data,
441 mdecoder->codec_context->pix_fmt, mdecoder->codec_context->width,
442 mdecoder->codec_context->height, 1);
443
444 const uint8_t* ptr[AV_NUM_DATA_POINTERS] = { 0 };
445 for (size_t x = 0; x < AV_NUM_DATA_POINTERS; x++)
446 ptr[x] = mdecoder->frame->data[x];
447
448 av_image_copy(frame->data, frame->linesize, ptr, mdecoder->frame->linesize,
449 mdecoder->codec_context->pix_fmt, mdecoder->codec_context->width,
450 mdecoder->codec_context->height);
451 av_free(frame);
452 }
453
454 return ret;
455}
456
457static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size,
458 UINT32 extensions)
459{
460 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
461 int len = 0;
462 int frame_size = 0;
463
464 if (mdecoder->decoded_size_max == 0)
465 mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16;
466
467 mdecoder->decoded_data = calloc(1, mdecoder->decoded_size_max);
468
469 if (!mdecoder->decoded_data)
470 return FALSE;
471
472 /* align the memory for SSE2 needs */
473 BYTE* dst = (BYTE*)(((uintptr_t)mdecoder->decoded_data + 15) & ~0x0F);
474 size_t dst_offset = (size_t)(dst - mdecoder->decoded_data);
475 const BYTE* src = data;
476 UINT32 src_size = data_size;
477
478 while (src_size > 0)
479 {
480 /* Ensure enough space for decoding */
481 if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
482 {
483 BYTE* tmp_data = NULL;
484 tmp_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max * 2 + 16);
485
486 if (!tmp_data)
487 return FALSE;
488
489 mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16;
490 mdecoder->decoded_data = tmp_data;
491 dst = (BYTE*)(((uintptr_t)mdecoder->decoded_data + 15) & ~0x0F);
492
493 const size_t diff = (size_t)(dst - mdecoder->decoded_data);
494 if (diff != dst_offset)
495 {
496 /* re-align the memory if the alignment has changed after realloc */
497 memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
498 dst_offset = diff;
499 }
500
501 dst += mdecoder->decoded_size;
502 }
503
504 frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size;
505#if LIBAVCODEC_VERSION_MAJOR < 52 || \
506 (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
507 len = avcodec_decode_audio2(mdecoder->codec_context, (int16_t*)dst, &frame_size, src,
508 src_size);
509#else
510 {
511#if LIBAVCODEC_VERSION_MAJOR < 55
512 AVFrame* decoded_frame = avcodec_alloc_frame();
513#else
514 AVFrame* decoded_frame = av_frame_alloc();
515#endif
516 int got_frame = 0;
517 AVPacket pkt = { 0 };
518#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
519 av_init_packet(&pkt);
520#endif
521
522 pkt.data = WINPR_CAST_CONST_PTR_AWAY(src, BYTE*);
523 pkt.size = src_size;
524#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
525 len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt);
526#else
527 len = avcodec_send_packet(mdecoder->codec_context, &pkt);
528 if (len > 0)
529 {
530 len = avcodec_receive_frame(mdecoder->codec_context, decoded_frame);
531 if (len == AVERROR(EAGAIN))
532 return TRUE;
533 }
534#endif
535
536 if (len >= 0 && got_frame)
537 {
538#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
539 const int channels = mdecoder->codec_context->ch_layout.nb_channels;
540#else
541 const int channels = mdecoder->codec_context->channels;
542#endif
543 frame_size = av_samples_get_buffer_size(NULL, channels, decoded_frame->nb_samples,
544 mdecoder->codec_context->sample_fmt, 1);
545 memcpy(dst, decoded_frame->data[0], frame_size);
546 }
547 else
548 {
549 frame_size = 0;
550 }
551
552 av_free(decoded_frame);
553 }
554#endif
555
556 if (len > 0)
557 {
558 src += len;
559 src_size -= len;
560 }
561
562 if (frame_size > 0)
563 {
564 mdecoder->decoded_size += frame_size;
565 dst += frame_size;
566 }
567 }
568
569 if (mdecoder->decoded_size == 0)
570 {
571 free(mdecoder->decoded_data);
572 mdecoder->decoded_data = NULL;
573 }
574 else if (dst_offset)
575 {
576 /* move the aligned decoded data to original place */
577 memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset,
578 mdecoder->decoded_size);
579 }
580
581 DEBUG_TSMF("data_size %" PRIu32 " decoded_size %" PRIu32 "", data_size, mdecoder->decoded_size);
582 return TRUE;
583}
584
585static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size,
586 UINT32 extensions)
587{
588 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
589
590 if (mdecoder->decoded_data)
591 {
592 free(mdecoder->decoded_data);
593 mdecoder->decoded_data = NULL;
594 }
595
596 mdecoder->decoded_size = 0;
597
598 switch (mdecoder->media_type)
599 {
600 case AVMEDIA_TYPE_VIDEO:
601 return tsmf_ffmpeg_decode_video(decoder, data, data_size, extensions);
602
603 case AVMEDIA_TYPE_AUDIO:
604 return tsmf_ffmpeg_decode_audio(decoder, data, data_size, extensions);
605
606 default:
607 WLog_ERR(TAG, "unknown media type.");
608 return FALSE;
609 }
610}
611
612static BYTE* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32* size)
613{
614 BYTE* buf = NULL;
615 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
616 *size = mdecoder->decoded_size;
617 buf = mdecoder->decoded_data;
618 mdecoder->decoded_data = NULL;
619 mdecoder->decoded_size = 0;
620 return buf;
621}
622
623static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder)
624{
625 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
626
627 switch (mdecoder->codec_context->pix_fmt)
628 {
629 case AV_PIX_FMT_YUV420P:
630 return RDP_PIXFMT_I420;
631
632 default:
633 WLog_ERR(TAG, "unsupported pixel format %u", mdecoder->codec_context->pix_fmt);
634 return (UINT32)-1;
635 }
636}
637
638static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32* width, UINT32* height)
639{
640 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
641
642 if (mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
643 {
644 *width = mdecoder->codec_context->width;
645 *height = mdecoder->codec_context->height;
646 return TRUE;
647 }
648 else
649 {
650 return FALSE;
651 }
652}
653
654static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
655{
656 TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder;
657
658 if (mdecoder->frame)
659 av_free(mdecoder->frame);
660
661 free(mdecoder->decoded_data);
662
663 if (mdecoder->codec_context)
664 {
665 free(mdecoder->codec_context->extradata);
666 mdecoder->codec_context->extradata = NULL;
667
668#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
669 avcodec_free_context(&mdecoder->codec_context);
670#else
671 if (mdecoder->prepared)
672 avcodec_close(mdecoder->codec_context);
673
674 av_free(mdecoder->codec_context);
675#endif
676 }
677
678 free(decoder);
679}
680
681static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT;
682static BOOL CALLBACK InitializeAvCodecs(PINIT_ONCE once, PVOID param, PVOID* context)
683{
684#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
685 avcodec_register_all();
686#endif
687 return TRUE;
688}
689
690FREERDP_ENTRY_POINT(UINT VCAPITYPE ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry(void* ptr))
691{
692 ITSMFDecoder** sptr = (ITSMFDecoder**)ptr;
693 WINPR_ASSERT(sptr);
694 *sptr = NULL;
695
696 TSMFFFmpegDecoder* decoder = NULL;
697 InitOnceExecuteOnce(&g_Initialized, InitializeAvCodecs, NULL, NULL);
698 WLog_DBG(TAG, "TSMFDecoderEntry FFMPEG");
699 decoder = (TSMFFFmpegDecoder*)calloc(1, sizeof(TSMFFFmpegDecoder));
700
701 if (!decoder)
702 return ERROR_OUTOFMEMORY;
703
704 decoder->iface.SetFormat = tsmf_ffmpeg_set_format;
705 decoder->iface.Decode = tsmf_ffmpeg_decode;
706 decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data;
707 decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format;
708 decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension;
709 decoder->iface.Free = tsmf_ffmpeg_free;
710 *sptr = &decoder->iface;
711 return CHANNEL_RC_OK;
712}