FreeRDP
h264_ffmpeg.c
1 
21 #include <freerdp/config.h>
22 
23 #include <winpr/wlog.h>
24 #include <freerdp/log.h>
25 #include <freerdp/codec/h264.h>
26 #include <libavcodec/avcodec.h>
27 #include <libavutil/opt.h>
28 
29 #include "h264.h"
30 
31 #ifdef WITH_VAAPI
32 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 9, 0)
33 #include <libavutil/hwcontext.h>
34 #else
35 #pragma warning You have asked for VA - API decoding, \
36  but your version of libavutil is too old !Disabling.
37 #undef WITH_VAAPI
38 #endif
39 #endif
40 
41 /* Fallback support for older libavcodec versions */
42 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
43 #define AV_CODEC_ID_H264 CODEC_ID_H264
44 #endif
45 
46 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2)
47 #define AV_CODEC_FLAG_LOOP_FILTER CODEC_FLAG_LOOP_FILTER
48 #define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED
49 #define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED
50 #endif
51 
52 #if LIBAVUTIL_VERSION_MAJOR < 52
53 #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
54 #endif
55 
56 /* Ubuntu 14.04 ships without the functions provided by avutil,
57  * so define error to string methods here. */
58 #if !defined(av_err2str)
59 static inline char* error_string(char* errbuf, size_t errbuf_size, int errnum)
60 {
61  av_strerror(errnum, errbuf, errbuf_size);
62  return errbuf;
63 }
64 
65 #define av_err2str(errnum) error_string((char[64]){ 0 }, 64, errnum)
66 #endif
67 
68 #ifdef WITH_VAAPI
69 #define VAAPI_DEVICE "/dev/dri/renderD128"
70 #endif
71 
72 typedef struct
73 {
74  const AVCodec* codecDecoder;
75  AVCodecContext* codecDecoderContext;
76  const AVCodec* codecEncoder;
77  AVCodecContext* codecEncoderContext;
78  AVCodecParserContext* codecParser;
79  AVFrame* videoFrame;
80 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
81  AVPacket bufferpacket;
82 #endif
83  AVPacket* packet;
84 #ifdef WITH_VAAPI
85  AVBufferRef* hwctx;
86  AVFrame* hwVideoFrame;
87  enum AVPixelFormat hw_pix_fmt;
88 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
89  AVBufferRef* hw_frames_ctx;
90 #endif
91 #endif
92 } H264_CONTEXT_LIBAVCODEC;
93 
94 static void libavcodec_destroy_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
95 {
96  H264_CONTEXT_LIBAVCODEC* sys = NULL;
97 
98  if (!h264 || !h264->subsystem)
99  return;
100 
101  sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
102 
103  if (sys->codecEncoderContext)
104  {
105  avcodec_close(sys->codecEncoderContext);
106 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
107  avcodec_free_context(&sys->codecEncoderContext);
108 #else
109  av_free(sys->codecEncoderContext);
110 #endif
111  }
112 
113  sys->codecEncoder = NULL;
114  sys->codecEncoderContext = NULL;
115 }
116 
117 static BOOL libavcodec_create_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
118 {
119  BOOL recreate = FALSE;
120  H264_CONTEXT_LIBAVCODEC* sys = NULL;
121 
122  if (!h264 || !h264->subsystem)
123  return FALSE;
124 
125  if ((h264->width > INT_MAX) || (h264->height > INT_MAX))
126  return FALSE;
127 
128  sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
129  if (!sys)
130  return FALSE;
131  recreate = !sys->codecEncoder || !sys->codecEncoderContext;
132 
133  if (sys->codecEncoderContext)
134  {
135  if ((sys->codecEncoderContext->width != (int)h264->width) ||
136  (sys->codecEncoderContext->height != (int)h264->height))
137  recreate = TRUE;
138  }
139 
140  if (!recreate)
141  return TRUE;
142 
143  libavcodec_destroy_encoder(h264);
144  sys->codecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);
145 
146  if (!sys->codecEncoder)
147  goto EXCEPTION;
148 
149  sys->codecEncoderContext = avcodec_alloc_context3(sys->codecEncoder);
150 
151  if (!sys->codecEncoderContext)
152  goto EXCEPTION;
153 
154  switch (h264->RateControlMode)
155  {
156  case H264_RATECONTROL_VBR:
157  sys->codecEncoderContext->bit_rate = h264->BitRate;
158  break;
159 
160  case H264_RATECONTROL_CQP:
161  /* TODO: sys->codecEncoderContext-> = h264->QP; */
162  break;
163 
164  default:
165  break;
166  }
167 
168  sys->codecEncoderContext->width = (int)MIN(INT32_MAX, h264->width);
169  sys->codecEncoderContext->height = (int)MIN(INT32_MAX, h264->height);
170  sys->codecEncoderContext->delay = 0;
171 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 13, 100)
172  sys->codecEncoderContext->framerate =
173  (AVRational){ WINPR_ASSERTING_INT_CAST(int, h264->FrameRate), 1 };
174 #endif
175  sys->codecEncoderContext->time_base =
176  (AVRational){ 1, WINPR_ASSERTING_INT_CAST(int, h264->FrameRate) };
177  av_opt_set(sys->codecEncoderContext, "preset", "medium", AV_OPT_SEARCH_CHILDREN);
178  av_opt_set(sys->codecEncoderContext, "tune", "zerolatency", AV_OPT_SEARCH_CHILDREN);
179  sys->codecEncoderContext->flags |= AV_CODEC_FLAG_LOOP_FILTER;
180  sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P;
181 
182  if (avcodec_open2(sys->codecEncoderContext, sys->codecEncoder, NULL) < 0)
183  goto EXCEPTION;
184 
185  return TRUE;
186 EXCEPTION:
187  libavcodec_destroy_encoder(h264);
188  return FALSE;
189 }
190 
191 static int libavcodec_decompress(H264_CONTEXT* WINPR_RESTRICT h264,
192  const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize)
193 {
194  union
195  {
196  const BYTE* cpv;
197  BYTE* pv;
198  } cnv;
199  int rc = -1;
200  int status = 0;
201  int gotFrame = 0;
202  AVPacket* packet = NULL;
203 
204  WINPR_ASSERT(h264);
205  WINPR_ASSERT(pSrcData || (SrcSize == 0));
206 
207  H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
208  BYTE** pYUVData = h264->pYUVData;
209  UINT32* iStride = h264->iStride;
210 
211  WINPR_ASSERT(sys);
212 
213 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
214  packet = &sys->bufferpacket;
215  WINPR_ASSERT(packet);
216  av_init_packet(packet);
217 #else
218  packet = av_packet_alloc();
219 #endif
220  if (!packet)
221  {
222  WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate AVPacket");
223  goto fail;
224  }
225 
226  cnv.cpv = pSrcData;
227  packet->data = cnv.pv;
228  packet->size = (int)MIN(SrcSize, INT32_MAX);
229 
230  WINPR_ASSERT(sys->codecDecoderContext);
231  /* avcodec_decode_video2 is deprecated with libavcodec 57.48.101 */
232 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
233  status = avcodec_send_packet(sys->codecDecoderContext, packet);
234 
235  if (status < 0)
236  {
237  WLog_Print(h264->log, WLOG_ERROR, "Failed to decode video frame (status=%d)", status);
238  goto fail;
239  }
240 
241  sys->videoFrame->format = AV_PIX_FMT_YUV420P;
242 
243  do
244  {
245 #ifdef WITH_VAAPI
246  status = avcodec_receive_frame(sys->codecDecoderContext,
247  sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
248 #else
249  status = avcodec_receive_frame(sys->codecDecoderContext, sys->videoFrame);
250 #endif
251  } while (status == AVERROR(EAGAIN));
252 
253  gotFrame = (status == 0);
254 #else
255 #ifdef WITH_VAAPI
256  status =
257  avcodec_decode_video2(sys->codecDecoderContext,
258  sys->hwctx ? sys->hwVideoFrame : sys->videoFrame, &gotFrame, packet);
259 #else
260  status = avcodec_decode_video2(sys->codecDecoderContext, sys->videoFrame, &gotFrame, packet);
261 #endif
262 #endif
263  if (status < 0)
264  {
265  WLog_Print(h264->log, WLOG_ERROR, "Failed to decode video frame (status=%d)", status);
266  goto fail;
267  }
268 
269 #ifdef WITH_VAAPI
270 
271  if (sys->hwctx)
272  {
273  if (sys->hwVideoFrame->format == sys->hw_pix_fmt)
274  {
275  sys->videoFrame->width = sys->hwVideoFrame->width;
276  sys->videoFrame->height = sys->hwVideoFrame->height;
277  status = av_hwframe_transfer_data(sys->videoFrame, sys->hwVideoFrame, 0);
278  }
279  else
280  {
281  status = av_frame_copy(sys->videoFrame, sys->hwVideoFrame);
282  }
283  }
284 
285  gotFrame = (status == 0);
286 
287  if (status < 0)
288  {
289  WLog_Print(h264->log, WLOG_ERROR, "Failed to transfer video frame (status=%d) (%s)", status,
290  av_err2str(status));
291  goto fail;
292  }
293 
294 #endif
295 #if 0
296  WLog_Print(h264->log, WLOG_INFO,
297  "libavcodec_decompress: frame decoded (status=%d, gotFrame=%d, width=%d, height=%d, Y=[%p,%d], U=[%p,%d], V=[%p,%d])",
298  status, gotFrame, sys->videoFrame->width, sys->videoFrame->height,
299  (void*) sys->videoFrame->data[0], sys->videoFrame->linesize[0],
300  (void*) sys->videoFrame->data[1], sys->videoFrame->linesize[1],
301  (void*) sys->videoFrame->data[2], sys->videoFrame->linesize[2]);
302 #endif
303 
304  if (gotFrame)
305  {
306  WINPR_ASSERT(sys->videoFrame);
307 
308  pYUVData[0] = sys->videoFrame->data[0];
309  pYUVData[1] = sys->videoFrame->data[1];
310  pYUVData[2] = sys->videoFrame->data[2];
311  iStride[0] = (UINT32)MAX(0, sys->videoFrame->linesize[0]);
312  iStride[1] = (UINT32)MAX(0, sys->videoFrame->linesize[1]);
313  iStride[2] = (UINT32)MAX(0, sys->videoFrame->linesize[2]);
314 
315  rc = 1;
316  }
317  else
318  rc = -2;
319 
320 fail:
321 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
322  av_packet_unref(packet);
323 #else
324  av_packet_free(&packet);
325 #endif
326 
327  return rc;
328 }
329 
330 static int libavcodec_compress(H264_CONTEXT* WINPR_RESTRICT h264,
331  const BYTE** WINPR_RESTRICT pSrcYuv,
332  const UINT32* WINPR_RESTRICT pStride,
333  BYTE** WINPR_RESTRICT ppDstData, UINT32* WINPR_RESTRICT pDstSize)
334 {
335  union
336  {
337  const BYTE* cpv;
338  uint8_t* pv;
339  } cnv;
340  int rc = -1;
341  int status = 0;
342  int gotFrame = 0;
343 
344  WINPR_ASSERT(h264);
345 
346  H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
347  WINPR_ASSERT(sys);
348 
349  if (!libavcodec_create_encoder(h264))
350  return -1;
351 
352 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
353  sys->packet = &sys->bufferpacket;
354  av_packet_unref(sys->packet);
355  av_init_packet(sys->packet);
356 #else
357  av_packet_free(&sys->packet);
358  sys->packet = av_packet_alloc();
359 #endif
360  if (!sys->packet)
361  {
362  WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate AVPacket");
363  goto fail;
364  }
365 
366  WINPR_ASSERT(sys->packet);
367  sys->packet->data = NULL;
368  sys->packet->size = 0;
369 
370  WINPR_ASSERT(sys->videoFrame);
371  WINPR_ASSERT(sys->codecEncoderContext);
372  sys->videoFrame->format = sys->codecEncoderContext->pix_fmt;
373  sys->videoFrame->width = sys->codecEncoderContext->width;
374  sys->videoFrame->height = sys->codecEncoderContext->height;
375 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 48, 100)
376  sys->videoFrame->colorspace = AVCOL_SPC_BT709;
377 #endif
378 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 92, 100)
379  sys->videoFrame->chroma_location = AVCHROMA_LOC_LEFT;
380 #endif
381  cnv.cpv = pSrcYuv[0];
382  sys->videoFrame->data[0] = cnv.pv;
383 
384  cnv.cpv = pSrcYuv[1];
385  sys->videoFrame->data[1] = cnv.pv;
386 
387  cnv.cpv = pSrcYuv[2];
388  sys->videoFrame->data[2] = cnv.pv;
389 
390  sys->videoFrame->linesize[0] = (int)pStride[0];
391  sys->videoFrame->linesize[1] = (int)pStride[1];
392  sys->videoFrame->linesize[2] = (int)pStride[2];
393  sys->videoFrame->pts++;
394  /* avcodec_encode_video2 is deprecated with libavcodec 57.48.101 */
395 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
396  status = avcodec_send_frame(sys->codecEncoderContext, sys->videoFrame);
397 
398  if (status < 0)
399  {
400  WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
401  av_err2str(status), status);
402  goto fail;
403  }
404 
405  status = avcodec_receive_packet(sys->codecEncoderContext, sys->packet);
406 
407  if (status < 0)
408  {
409  WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
410  av_err2str(status), status);
411  goto fail;
412  }
413 
414  gotFrame = (status == 0);
415 #elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
416 
417  do
418  {
419  status = avcodec_encode_video2(sys->codecEncoderContext, sys->packet, sys->videoFrame,
420  &gotFrame);
421  } while ((status >= 0) && (gotFrame == 0));
422 
423 #else
424  sys->packet->size =
425  avpicture_get_size(sys->codecDecoderContext->pix_fmt, sys->codecDecoderContext->width,
426  sys->codecDecoderContext->height);
427  sys->packet->data = av_malloc(sys->packet->size);
428 
429  if (!sys->packet->data)
430  status = -1;
431  else
432  {
433  status = avcodec_encode_video(sys->codecDecoderContext, sys->packet->data,
434  sys->packet->size, sys->videoFrame);
435  }
436 
437 #endif
438 
439  if (status < 0)
440  {
441  WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
442  av_err2str(status), status);
443  goto fail;
444  }
445 
446  WINPR_ASSERT(sys->packet);
447  *ppDstData = sys->packet->data;
448  *pDstSize = (UINT32)MAX(0, sys->packet->size);
449 
450  if (!gotFrame)
451  {
452  WLog_Print(h264->log, WLOG_ERROR, "Did not get frame! (%s [%d])", av_err2str(status),
453  status);
454  rc = -2;
455  }
456  else
457  rc = 1;
458 fail:
459  return rc;
460 }
461 
462 static void libavcodec_uninit(H264_CONTEXT* h264)
463 {
464  WINPR_ASSERT(h264);
465 
466  H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
467 
468  if (!sys)
469  return;
470 
471  if (sys->packet)
472  {
473 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
474  av_packet_unref(sys->packet);
475 #else
476  av_packet_free(&sys->packet);
477 #endif
478  }
479 
480  if (sys->videoFrame)
481  {
482 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
483  av_frame_free(&sys->videoFrame);
484 #else
485  av_free(sys->videoFrame);
486 #endif
487  }
488 
489 #ifdef WITH_VAAPI
490 
491  if (sys->hwVideoFrame)
492  {
493 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
494  av_frame_free(&sys->hwVideoFrame);
495 #else
496  av_free(sys->hwVideoFrame);
497 #endif
498  }
499 
500  if (sys->hwctx)
501  av_buffer_unref(&sys->hwctx);
502 
503 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
504 
505  if (sys->hw_frames_ctx)
506  av_buffer_unref(&sys->hw_frames_ctx);
507 
508 #endif
509 #endif
510 
511  if (sys->codecParser)
512  av_parser_close(sys->codecParser);
513 
514  if (sys->codecDecoderContext)
515  {
516  avcodec_close(sys->codecDecoderContext);
517 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
518  avcodec_free_context(&sys->codecDecoderContext);
519 #else
520  av_free(sys->codecDecoderContext);
521 #endif
522  }
523 
524  libavcodec_destroy_encoder(h264);
525  free(sys);
526  h264->pSystemData = NULL;
527 }
528 
529 #ifdef WITH_VAAPI
530 static enum AVPixelFormat libavcodec_get_format(struct AVCodecContext* ctx,
531  const enum AVPixelFormat* fmts)
532 {
533  WINPR_ASSERT(ctx);
534 
535  H264_CONTEXT* h264 = (H264_CONTEXT*)ctx->opaque;
536  WINPR_ASSERT(h264);
537 
538  H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
539  WINPR_ASSERT(sys);
540 
541  for (const enum AVPixelFormat* p = fmts; *p != AV_PIX_FMT_NONE; p++)
542  {
543  if (*p == sys->hw_pix_fmt)
544  {
545 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
546  sys->hw_frames_ctx = av_hwframe_ctx_alloc(sys->hwctx);
547 
548  if (!sys->hw_frames_ctx)
549  {
550  return AV_PIX_FMT_NONE;
551  }
552 
553  sys->codecDecoderContext->pix_fmt = *p;
554  AVHWFramesContext* frames = (AVHWFramesContext*)sys->hw_frames_ctx->data;
555  frames->format = *p;
556  frames->height = sys->codecDecoderContext->coded_height;
557  frames->width = sys->codecDecoderContext->coded_width;
558  frames->sw_format =
559  (sys->codecDecoderContext->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? AV_PIX_FMT_P010
560  : AV_PIX_FMT_NV12);
561  frames->initial_pool_size = 20;
562 
563  if (sys->codecDecoderContext->active_thread_type & FF_THREAD_FRAME)
564  frames->initial_pool_size += sys->codecDecoderContext->thread_count;
565 
566  int err = av_hwframe_ctx_init(sys->hw_frames_ctx);
567 
568  if (err < 0)
569  {
570  WLog_Print(h264->log, WLOG_ERROR, "Could not init hwframes context: %s",
571  av_err2str(err));
572  return AV_PIX_FMT_NONE;
573  }
574 
575  sys->codecDecoderContext->hw_frames_ctx = av_buffer_ref(sys->hw_frames_ctx);
576 #endif
577  return *p;
578  }
579  }
580 
581  return AV_PIX_FMT_NONE;
582 }
583 #endif
584 
585 static BOOL libavcodec_init(H264_CONTEXT* h264)
586 {
587  H264_CONTEXT_LIBAVCODEC* sys = NULL;
588 
589  WINPR_ASSERT(h264);
590  sys = (H264_CONTEXT_LIBAVCODEC*)calloc(1, sizeof(H264_CONTEXT_LIBAVCODEC));
591 
592  if (!sys)
593  {
594  goto EXCEPTION;
595  }
596 
597  h264->pSystemData = (void*)sys;
598 
599 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
600  avcodec_register_all();
601 #endif
602 
603  if (!h264->Compressor)
604  {
605  sys->codecDecoder = avcodec_find_decoder(AV_CODEC_ID_H264);
606 
607  if (!sys->codecDecoder)
608  {
609  WLog_Print(h264->log, WLOG_ERROR, "Failed to find libav H.264 codec");
610  goto EXCEPTION;
611  }
612 
613  sys->codecDecoderContext = avcodec_alloc_context3(sys->codecDecoder);
614 
615  if (!sys->codecDecoderContext)
616  {
617  WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav codec context");
618  goto EXCEPTION;
619  }
620 
621 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100)
622  if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED)
623  {
624  sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED;
625  }
626 #endif
627 
628 #ifdef WITH_VAAPI
629 
630  if (!sys->hwctx)
631  {
632  int ret =
633  av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI, VAAPI_DEVICE, NULL, 0);
634 
635  if (ret < 0)
636  {
637  WLog_Print(h264->log, WLOG_ERROR,
638  "Could not initialize hardware decoder, falling back to software: %s",
639  av_err2str(ret));
640  sys->hwctx = NULL;
641  goto fail_hwdevice_create;
642  }
643  }
644  WLog_Print(h264->log, WLOG_INFO, "Using VAAPI for accelerated H264 decoding");
645 
646  sys->codecDecoderContext->get_format = libavcodec_get_format;
647  sys->hw_pix_fmt = AV_PIX_FMT_VAAPI;
648 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100)
649  sys->codecDecoderContext->hw_device_ctx = av_buffer_ref(sys->hwctx);
650 #endif
651  sys->codecDecoderContext->opaque = (void*)h264;
652  fail_hwdevice_create:
653 #endif
654 
655  if (avcodec_open2(sys->codecDecoderContext, sys->codecDecoder, NULL) < 0)
656  {
657  WLog_Print(h264->log, WLOG_ERROR, "Failed to open libav codec");
658  goto EXCEPTION;
659  }
660 
661  sys->codecParser = av_parser_init(AV_CODEC_ID_H264);
662 
663  if (!sys->codecParser)
664  {
665  WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize libav parser");
666  goto EXCEPTION;
667  }
668  }
669 
670 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
671  sys->videoFrame = av_frame_alloc();
672 #ifdef WITH_VAAPI
673  sys->hwVideoFrame = av_frame_alloc();
674 #endif
675 #else
676  sys->videoFrame = avcodec_alloc_frame();
677 #endif
678 
679  if (!sys->videoFrame)
680  {
681  WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav frame");
682  goto EXCEPTION;
683  }
684 
685 #ifdef WITH_VAAPI
686 
687  if (!sys->hwVideoFrame)
688  {
689  WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav hw frame");
690  goto EXCEPTION;
691  }
692 
693 #endif
694  sys->videoFrame->pts = 0;
695  return TRUE;
696 EXCEPTION:
697  libavcodec_uninit(h264);
698  return FALSE;
699 }
700 
701 const H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec = { "libavcodec", libavcodec_init,
702  libavcodec_uninit, libavcodec_decompress,
703  libavcodec_compress };