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 |
|
|
/** |
23 |
|
|
* @file |
24 |
|
|
* Simple wrapper to store an AVFrame and forward it as AVPacket. |
25 |
|
|
*/ |
26 |
|
|
|
27 |
|
|
#include "avcodec.h" |
28 |
|
|
#include "decode.h" |
29 |
|
|
#include "internal.h" |
30 |
|
|
|
31 |
|
|
#include "libavutil/internal.h" |
32 |
|
|
#include "libavutil/frame.h" |
33 |
|
|
#include "libavutil/buffer.h" |
34 |
|
|
#include "libavutil/pixdesc.h" |
35 |
|
|
|
36 |
|
35 |
static void wrapped_avframe_release_buffer(void *unused, uint8_t *data) |
37 |
|
|
{ |
38 |
|
35 |
AVFrame *frame = (AVFrame *)data; |
39 |
|
|
|
40 |
|
35 |
av_frame_free(&frame); |
41 |
|
35 |
} |
42 |
|
|
|
43 |
|
35 |
static int wrapped_avframe_encode(AVCodecContext *avctx, AVPacket *pkt, |
44 |
|
|
const AVFrame *frame, int *got_packet) |
45 |
|
|
{ |
46 |
|
35 |
AVFrame *wrapped = av_frame_clone(frame); |
47 |
|
|
uint8_t *data; |
48 |
|
35 |
int size = sizeof(*wrapped) + AV_INPUT_BUFFER_PADDING_SIZE; |
49 |
|
|
|
50 |
✗✓ |
35 |
if (!wrapped) |
51 |
|
|
return AVERROR(ENOMEM); |
52 |
|
|
|
53 |
|
35 |
data = av_mallocz(size); |
54 |
✗✓ |
35 |
if (!data) { |
55 |
|
|
av_frame_free(&wrapped); |
56 |
|
|
return AVERROR(ENOMEM); |
57 |
|
|
} |
58 |
|
|
|
59 |
|
35 |
pkt->buf = av_buffer_create(data, size, |
60 |
|
|
wrapped_avframe_release_buffer, NULL, |
61 |
|
|
AV_BUFFER_FLAG_READONLY); |
62 |
✗✓ |
35 |
if (!pkt->buf) { |
63 |
|
|
av_frame_free(&wrapped); |
64 |
|
|
av_freep(&data); |
65 |
|
|
return AVERROR(ENOMEM); |
66 |
|
|
} |
67 |
|
|
|
68 |
|
35 |
av_frame_move_ref((AVFrame*)data, wrapped); |
69 |
|
35 |
av_frame_free(&wrapped); |
70 |
|
|
|
71 |
|
35 |
pkt->data = data; |
72 |
|
35 |
pkt->size = sizeof(*wrapped); |
73 |
|
|
|
74 |
|
35 |
pkt->flags |= AV_PKT_FLAG_KEY; |
75 |
|
35 |
*got_packet = 1; |
76 |
|
35 |
return 0; |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
static int wrapped_avframe_decode(AVCodecContext *avctx, void *data, |
80 |
|
|
int *got_frame, AVPacket *pkt) |
81 |
|
|
{ |
82 |
|
|
AVFrame *in, *out; |
83 |
|
|
int err; |
84 |
|
|
|
85 |
|
|
if (!(pkt->flags & AV_PKT_FLAG_TRUSTED)) { |
86 |
|
|
// This decoder is not usable with untrusted input. |
87 |
|
|
return AVERROR(EPERM); |
88 |
|
|
} |
89 |
|
|
|
90 |
|
|
if (pkt->size < sizeof(AVFrame)) |
91 |
|
|
return AVERROR(EINVAL); |
92 |
|
|
|
93 |
|
|
in = (AVFrame*)pkt->data; |
94 |
|
|
out = data; |
95 |
|
|
|
96 |
|
|
err = ff_decode_frame_props(avctx, out); |
97 |
|
|
if (err < 0) |
98 |
|
|
return err; |
99 |
|
|
|
100 |
|
|
av_frame_move_ref(out, in); |
101 |
|
|
|
102 |
|
|
err = ff_attach_decode_data(out); |
103 |
|
|
if (err < 0) { |
104 |
|
|
av_frame_unref(out); |
105 |
|
|
return err; |
106 |
|
|
} |
107 |
|
|
|
108 |
|
|
*got_frame = 1; |
109 |
|
|
return 0; |
110 |
|
|
} |
111 |
|
|
|
112 |
|
|
AVCodec ff_wrapped_avframe_encoder = { |
113 |
|
|
.name = "wrapped_avframe", |
114 |
|
|
.long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"), |
115 |
|
|
.type = AVMEDIA_TYPE_VIDEO, |
116 |
|
|
.id = AV_CODEC_ID_WRAPPED_AVFRAME, |
117 |
|
|
.encode2 = wrapped_avframe_encode, |
118 |
|
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, |
119 |
|
|
}; |
120 |
|
|
|
121 |
|
|
AVCodec ff_wrapped_avframe_decoder = { |
122 |
|
|
.name = "wrapped_avframe", |
123 |
|
|
.long_name = NULL_IF_CONFIG_SMALL("AVPacket to AVFrame passthrough"), |
124 |
|
|
.type = AVMEDIA_TYPE_VIDEO, |
125 |
|
|
.id = AV_CODEC_ID_WRAPPED_AVFRAME, |
126 |
|
|
.decode = wrapped_avframe_decode, |
127 |
|
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, |
128 |
|
|
}; |