1 #include <libavutil/frame.h>
2
3 #include "audio/aframe.h"
4 #include "common/av_common.h"
5 #include "demux/packet.h"
6 #include "video/mp_image.h"
7
8 #include "frame.h"
9
10 struct frame_handler {
11 const char *name;
12 bool is_data;
13 bool is_signaling;
14 void *(*new_ref)(void *data);
15 double (*get_pts)(void *data);
16 void (*set_pts)(void *data, double pts);
17 int (*approx_size)(void *data);
18 AVFrame *(*new_av_ref)(void *data);
19 void *(*from_av_ref)(AVFrame *data);
20 void (*free)(void *data);
21 };
22
video_ref(void * data)23 static void *video_ref(void *data)
24 {
25 return mp_image_new_ref(data);
26 }
27
video_get_pts(void * data)28 static double video_get_pts(void *data)
29 {
30 return ((struct mp_image *)data)->pts;
31 }
32
video_set_pts(void * data,double pts)33 static void video_set_pts(void *data, double pts)
34 {
35 ((struct mp_image *)data)->pts = pts;
36 }
37
video_approx_size(void * data)38 static int video_approx_size(void *data)
39 {
40 return mp_image_approx_byte_size(data);
41 }
42
video_new_av_ref(void * data)43 static AVFrame *video_new_av_ref(void *data)
44 {
45 return mp_image_to_av_frame(data);
46 }
47
video_from_av_ref(AVFrame * data)48 static void *video_from_av_ref(AVFrame *data)
49 {
50 return mp_image_from_av_frame(data);
51 }
52
audio_ref(void * data)53 static void *audio_ref(void *data)
54 {
55 return mp_aframe_new_ref(data);
56 }
57
audio_get_pts(void * data)58 static double audio_get_pts(void *data)
59 {
60 return mp_aframe_get_pts(data);
61 }
62
audio_set_pts(void * data,double pts)63 static void audio_set_pts(void *data, double pts)
64 {
65 mp_aframe_set_pts(data, pts);
66 }
67
audio_approx_size(void * data)68 static int audio_approx_size(void *data)
69 {
70 return mp_aframe_approx_byte_size(data);
71 }
72
audio_new_av_ref(void * data)73 static AVFrame *audio_new_av_ref(void *data)
74 {
75 return mp_aframe_to_avframe(data);
76 }
77
audio_from_av_ref(AVFrame * data)78 static void *audio_from_av_ref(AVFrame *data)
79 {
80 return mp_aframe_from_avframe(data);
81 }
82
packet_ref(void * data)83 static void *packet_ref(void *data)
84 {
85 return demux_copy_packet(data);
86 }
87
88 static const struct frame_handler frame_handlers[] = {
89 [MP_FRAME_NONE] = {
90 .name = "none",
91 },
92 [MP_FRAME_EOF] = {
93 .name = "eof",
94 .is_signaling = true,
95 },
96 [MP_FRAME_VIDEO] = {
97 .name = "video",
98 .is_data = true,
99 .new_ref = video_ref,
100 .get_pts = video_get_pts,
101 .set_pts = video_set_pts,
102 .approx_size = video_approx_size,
103 .new_av_ref = video_new_av_ref,
104 .from_av_ref = video_from_av_ref,
105 .free = talloc_free,
106 },
107 [MP_FRAME_AUDIO] = {
108 .name = "audio",
109 .is_data = true,
110 .new_ref = audio_ref,
111 .get_pts = audio_get_pts,
112 .set_pts = audio_set_pts,
113 .approx_size = audio_approx_size,
114 .new_av_ref = audio_new_av_ref,
115 .from_av_ref = audio_from_av_ref,
116 .free = talloc_free,
117 },
118 [MP_FRAME_PACKET] = {
119 .name = "packet",
120 .is_data = true,
121 .new_ref = packet_ref,
122 .free = talloc_free,
123 },
124 };
125
mp_frame_type_str(enum mp_frame_type t)126 const char *mp_frame_type_str(enum mp_frame_type t)
127 {
128 return frame_handlers[t].name;
129 }
130
mp_frame_is_data(struct mp_frame frame)131 bool mp_frame_is_data(struct mp_frame frame)
132 {
133 return frame_handlers[frame.type].is_data;
134 }
135
mp_frame_is_signaling(struct mp_frame frame)136 bool mp_frame_is_signaling(struct mp_frame frame)
137 {
138 return frame_handlers[frame.type].is_signaling;
139 }
140
mp_frame_unref(struct mp_frame * frame)141 void mp_frame_unref(struct mp_frame *frame)
142 {
143 if (!frame)
144 return;
145
146 if (frame_handlers[frame->type].free)
147 frame_handlers[frame->type].free(frame->data);
148
149 *frame = (struct mp_frame){0};
150 }
151
mp_frame_ref(struct mp_frame frame)152 struct mp_frame mp_frame_ref(struct mp_frame frame)
153 {
154 if (frame_handlers[frame.type].new_ref) {
155 assert(frame.data);
156 frame.data = frame_handlers[frame.type].new_ref(frame.data);
157 if (!frame.data)
158 frame.type = MP_FRAME_NONE;
159 }
160 return frame;
161 }
162
mp_frame_get_pts(struct mp_frame frame)163 double mp_frame_get_pts(struct mp_frame frame)
164 {
165 if (frame_handlers[frame.type].get_pts)
166 return frame_handlers[frame.type].get_pts(frame.data);
167 return MP_NOPTS_VALUE;
168 }
169
mp_frame_set_pts(struct mp_frame frame,double pts)170 void mp_frame_set_pts(struct mp_frame frame, double pts)
171 {
172 if (frame_handlers[frame.type].get_pts)
173 frame_handlers[frame.type].set_pts(frame.data, pts);
174 }
175
mp_frame_approx_size(struct mp_frame frame)176 int mp_frame_approx_size(struct mp_frame frame)
177 {
178 if (frame_handlers[frame.type].approx_size)
179 return frame_handlers[frame.type].approx_size(frame.data);
180 return 0;
181 }
182
mp_frame_to_av(struct mp_frame frame,struct AVRational * tb)183 AVFrame *mp_frame_to_av(struct mp_frame frame, struct AVRational *tb)
184 {
185 if (!frame_handlers[frame.type].new_av_ref)
186 return NULL;
187
188 AVFrame *res = frame_handlers[frame.type].new_av_ref(frame.data);
189 if (!res)
190 return NULL;
191
192 res->pts = mp_pts_to_av(mp_frame_get_pts(frame), tb);
193 return res;
194 }
195
mp_frame_from_av(enum mp_frame_type type,struct AVFrame * frame,struct AVRational * tb)196 struct mp_frame mp_frame_from_av(enum mp_frame_type type, struct AVFrame *frame,
197 struct AVRational *tb)
198 {
199 struct mp_frame res = {type};
200
201 if (!frame_handlers[res.type].from_av_ref)
202 return MP_NO_FRAME;
203
204 res.data = frame_handlers[res.type].from_av_ref(frame);
205 if (!res.data)
206 return MP_NO_FRAME;
207
208 mp_frame_set_pts(res, mp_pts_from_av(frame->pts, tb));
209 return res;
210 }
211