1 /*
2 * Copyright (C) 2000-2018 the xine project
3 *
4 * This file is part of xine, a free video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * foovideo.c: This is a reference video decoder for the xine multimedia
21 * player. It really works too! It will output frames of packed YUY2 data
22 * where each byte in the map is the same value, which is 3 larger than the
23 * value from the last frame. This creates a slowly rotating solid color
24 * frame when the frames are played in succession.
25 */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36
37 #include <xine/xine_internal.h>
38 #include <xine/video_out.h>
39 #include <xine/buffer.h>
40 #include <xine/xineutils.h>
41 #include "bswap.h"
42
43 #define VIDEOBUFSIZE 128*1024
44
45 typedef struct {
46 video_decoder_class_t decoder_class;
47 } foovideo_class_t;
48
49 typedef struct foovideo_decoder_s {
50 video_decoder_t video_decoder; /* parent video decoder structure */
51
52 foovideo_class_t *class;
53 xine_stream_t *stream;
54
55 /* these are traditional variables in a video decoder object */
56 uint64_t video_step; /* frame duration in pts units */
57 int decoder_ok; /* current decoder status */
58 int skipframes;
59
60 unsigned char *buf; /* the accumulated buffer data */
61 int bufsize; /* the maximum size of buf */
62 int size; /* the current size of buf */
63
64 int width; /* the width of a video frame */
65 int height; /* the height of a video frame */
66 double ratio; /* the width to height ratio */
67
68 /* these are variables exclusive to the foo video decoder */
69 unsigned char current_yuv_byte;
70
71 } foovideo_decoder_t;
72
73 /**************************************************************************
74 * foovideo specific decode functions
75 *************************************************************************/
76
77 /**************************************************************************
78 * xine video plugin functions
79 *************************************************************************/
80
81 /*
82 * This function receives a buffer of data from the demuxer layer and
83 * figures out how to handle it based on its header flags.
84 */
foovideo_decode_data(video_decoder_t * this_gen,buf_element_t * buf)85 static void foovideo_decode_data (video_decoder_t *this_gen,
86 buf_element_t *buf) {
87
88 foovideo_decoder_t *this = (foovideo_decoder_t *) this_gen;
89 xine_bmiheader *bih;
90
91 vo_frame_t *img; /* video out frame */
92
93 /* a video decoder does not care about this flag (?) */
94 if (buf->decoder_flags & BUF_FLAG_PREVIEW)
95 return;
96
97 if (buf->decoder_flags & BUF_FLAG_FRAMERATE) {
98 this->video_step = buf->decoder_info[0];
99 _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step);
100 }
101
102 if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */
103 (this->stream->video_out->open) (this->stream->video_out, this->stream);
104
105 free(this->buf);
106
107 bih = (xine_bmiheader *) buf->content;
108 this->width = bih->biWidth;
109 this->height = bih->biHeight;
110 this->ratio = (double)this->width/(double)this->height;
111
112 if (this->buf)
113 free (this->buf);
114 this->bufsize = VIDEOBUFSIZE;
115 this->buf = malloc(this->bufsize);
116 this->size = 0;
117
118 /* take this opportunity to load the stream/meta info */
119 _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "foovideo");
120
121 /* do anything else relating to initializing this decoder */
122 this->current_yuv_byte = 0;
123
124 this->decoder_ok = 1;
125
126 return;
127 } else if (this->decoder_ok) {
128
129 if (this->size + buf->size > this->bufsize) {
130 this->bufsize = this->size + 2 * buf->size;
131 this->buf = realloc (this->buf, this->bufsize);
132 }
133
134 xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size);
135
136 this->size += buf->size;
137
138 if (buf->decoder_flags & BUF_FLAG_FRAME_END) {
139
140 img = this->stream->video_out->get_frame (this->stream->video_out,
141 this->width, this->height,
142 this->ratio,
143 XINE_IMGFMT_YUY2, VO_BOTH_FIELDS);
144 if (!img) {
145 this->size = 0;
146 return;
147 }
148
149 img->duration = this->video_step;
150 img->pts = buf->pts;
151 img->bad_frame = 0;
152
153 memset(img->base[0], this->current_yuv_byte,
154 this->width * this->height * 2);
155 this->current_yuv_byte += 3;
156
157 img->draw(img, this->stream);
158 img->free(img);
159
160 this->size = 0;
161 }
162 }
163 }
164
165 /*
166 * This function is called when xine needs to flush the system.
167 */
foovideo_flush(video_decoder_t * this_gen)168 static void foovideo_flush (video_decoder_t *this_gen) {
169 }
170
171 /*
172 * This function resets the video decoder.
173 */
foovideo_reset(video_decoder_t * this_gen)174 static void foovideo_reset (video_decoder_t *this_gen) {
175 foovideo_decoder_t *this = (foovideo_decoder_t *) this_gen;
176
177 this->size = 0;
178 }
179
180 /*
181 * The decoder should forget any stored pts values here.
182 */
foovideo_discontinuity(video_decoder_t * this_gen)183 static void foovideo_discontinuity (video_decoder_t *this_gen) {
184 foovideo_decoder_t *this = (foovideo_decoder_t *) this_gen;
185
186 }
187
188 /*
189 * This function frees the video decoder instance allocated to the decoder.
190 */
foovideo_dispose(video_decoder_t * this_gen)191 static void foovideo_dispose (video_decoder_t *this_gen) {
192
193 foovideo_decoder_t *this = (foovideo_decoder_t *) this_gen;
194
195 free (this->buf);
196
197 if (this->decoder_ok) {
198 this->decoder_ok = 0;
199 this->stream->video_out->close(this->stream->video_out, this->stream);
200 }
201
202 free (this_gen);
203 }
204
205 /*
206 * This function allocates, initializes, and returns a private video
207 * decoder structure.
208 */
open_plugin(video_decoder_class_t * class_gen,xine_stream_t * stream)209 static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
210
211 foovideo_decoder_t *this ;
212
213 this = (foovideo_decoder_t *) calloc(1, sizeof(foovideo_decoder_t));
214
215 this->video_decoder.decode_data = foovideo_decode_data;
216 this->video_decoder.flush = foovideo_flush;
217 this->video_decoder.reset = foovideo_reset;
218 this->video_decoder.discontinuity = foovideo_discontinuity;
219 this->video_decoder.dispose = foovideo_dispose;
220 this->size = 0;
221
222 this->stream = stream;
223 this->class = (foovideo_class_t *) class_gen;
224
225 this->decoder_ok = 0;
226 this->buf = NULL;
227
228 return &this->video_decoder;
229 }
230
231 /*
232 * This function frees the video decoder class and any other memory that was
233 * allocated.
234 */
dispose_class(video_decoder_class_t * this)235 static void dispose_class (video_decoder_class_t *this) {
236 free (this);
237 }
238
239 /*
240 * This function allocates a private video decoder class and initializes
241 * the class's member functions.
242 */
init_plugin(xine_t * xine,const void * data)243 static void *init_plugin (xine_t *xine, const void *data) {
244
245 foovideo_class_t *this;
246
247 this = (foovideo_class_t *) calloc(1, sizeof(foovideo_class_t));
248
249 this->decoder_class.open_plugin = open_plugin;
250 this->decoder_class.identifier = "foovideo";
251 this->decoder_class.description = N_("foovideo: reference xine video decoder plugin");
252 this->decoder_class.dispose = dispose_class;
253
254 return this;
255 }
256
257 /*
258 * This is a list of all of the internal xine video buffer types that
259 * this decoder is able to handle. Check src/xine-engine/buffer.h for a
260 * list of valid buffer types (and add a new one if the one you need does
261 * not exist). Terminate the list with a 0.
262 */
263 static const uint32_t video_types[] = {
264 /* BUF_VIDEO_FOOVIDEO, */
265 BUF_VIDEO_VQA,
266 BUF_VIDEO_SORENSON_V3,
267 0
268 };
269
270 /*
271 * This data structure combines the list of supported xine buffer types and
272 * the priority that the plugin should be given with respect to other
273 * plugins that handle the same buffer type. A plugin with priority (n+1)
274 * will be used instead of a plugin with priority (n).
275 */
276 static const decoder_info_t dec_info_video = {
277 .supported_types = video_types,
278 .priority = 5,
279 };
280
281 /*
282 * The plugin catalog entry. This is the only information that this plugin
283 * will export to the public.
284 */
285 const plugin_info_t xine_plugin_info[] EXPORTED = {
286 /* { type, API, "name", version, special_info, init_function } */
287 { PLUGIN_VIDEO_DECODER, 19, "foovideo", XINE_VERSION_CODE, &dec_info_video, init_plugin },
288 { PLUGIN_NONE, 0, NULL, 0, NULL, NULL }
289 };
290