You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
3.5KB

  1. /*
  2. * AVFrame wrapper
  3. * Copyright (c) 2015 Luca Barbato
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * Simple wrapper to store an AVFrame and forward it as AVPacket.
  24. */
  25. #include "avcodec.h"
  26. #include "decode.h"
  27. #include "internal.h"
  28. #include "libavutil/internal.h"
  29. #include "libavutil/frame.h"
  30. #include "libavutil/buffer.h"
  31. #include "libavutil/pixdesc.h"
  32. static void wrapped_avframe_release_buffer(void *unused, uint8_t *data)
  33. {
  34. AVFrame *frame = (AVFrame *)data;
  35. av_frame_free(&frame);
  36. }
  37. static int wrapped_avframe_encode(AVCodecContext *avctx, AVPacket *pkt,
  38. const AVFrame *frame, int *got_packet)
  39. {
  40. AVFrame *wrapped = av_frame_clone(frame);
  41. uint8_t *data;
  42. int size = sizeof(*wrapped) + AV_INPUT_BUFFER_PADDING_SIZE;
  43. if (!wrapped)
  44. return AVERROR(ENOMEM);
  45. data = av_mallocz(size);
  46. if (!data) {
  47. av_frame_free(&wrapped);
  48. return AVERROR(ENOMEM);
  49. }
  50. pkt->buf = av_buffer_create(data, size,
  51. wrapped_avframe_release_buffer, NULL,
  52. AV_BUFFER_FLAG_READONLY);
  53. if (!pkt->buf) {
  54. av_frame_free(&wrapped);
  55. av_freep(&data);
  56. return AVERROR(ENOMEM);
  57. }
  58. av_frame_move_ref((AVFrame*)data, wrapped);
  59. av_frame_free(&wrapped);
  60. pkt->data = data;
  61. pkt->size = sizeof(*wrapped);
  62. pkt->flags |= AV_PKT_FLAG_KEY;
  63. *got_packet = 1;
  64. return 0;
  65. }
  66. static int wrapped_avframe_decode(AVCodecContext *avctx, void *data,
  67. int *got_frame, AVPacket *pkt)
  68. {
  69. AVFrame *in, *out;
  70. int err;
  71. if (!(pkt->flags & AV_PKT_FLAG_TRUSTED)) {
  72. // This decoder is not usable with untrusted input.
  73. return AVERROR(EPERM);
  74. }
  75. if (pkt->size < sizeof(AVFrame))
  76. return AVERROR(EINVAL);
  77. in = (AVFrame*)pkt->data;
  78. out = data;
  79. err = ff_decode_frame_props(avctx, out);
  80. if (err < 0)
  81. return err;
  82. av_frame_move_ref(out, in);
  83. err = ff_attach_decode_data(out);
  84. if (err < 0) {
  85. av_frame_unref(out);
  86. return err;
  87. }
  88. *got_frame = 1;
  89. return 0;
  90. }
  91. AVCodec ff_wrapped_avframe_encoder = {
  92. .name = "wrapped_avframe",
  93. .long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"),
  94. .type = AVMEDIA_TYPE_VIDEO,
  95. .id = AV_CODEC_ID_WRAPPED_AVFRAME,
  96. .encode2 = wrapped_avframe_encode,
  97. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
  98. };
  99. AVCodec ff_wrapped_avframe_decoder = {
  100. .name = "wrapped_avframe",
  101. .long_name = NULL_IF_CONFIG_SMALL("AVPacket to AVFrame passthrough"),
  102. .type = AVMEDIA_TYPE_VIDEO,
  103. .id = AV_CODEC_ID_WRAPPED_AVFRAME,
  104. .decode = wrapped_avframe_decode,
  105. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
  106. };