3 * copyright (c) 2001 Rik Snel
4 * (using yuv4mpeg*.[ch] from mjpeg.sourceforge.net)
5 * (derived from demux_viv.c)
6 * older YUV4MPEG (used by xawtv) support by Alex Beregszaszi
8 * This file is part of MPlayer.
10 * MPlayer is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * MPlayer is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <string.h> /* strtok */
34 #include "stream/stream.h"
40 y4m_stream_info_t
* si
;
44 static int y4m_check_file(demuxer_t
* demuxer
){
45 int orig_pos
= stream_tell(demuxer
->stream
);
49 mp_msg(MSGT_DEMUX
, MSGL_V
, "Checking for YUV4MPEG2\n");
51 if(stream_read(demuxer
->stream
, buf
, 9)!=9)
56 if (strncmp("YUV4MPEG2", buf
, 9) && strncmp("YUV4MPEG ", buf
, 9)) {
60 demuxer
->priv
= malloc(sizeof(y4m_priv_t
));
65 if (!strncmp("YUV4MPEG ", buf
, 9))
67 mp_msg(MSGT_DEMUX
, MSGL_V
, "Found older YUV4MPEG format (used by xawtv)\n");
71 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Success: YUV4MPEG2\n");
73 stream_seek(demuxer
->stream
, orig_pos
);
75 return DEMUXER_TYPE_Y4M
;
78 static void read_streaminfo(demuxer_t
*demuxer
);
81 // 0 = EOF or no stream found
82 // 1 = successfully read a packet
83 static int demux_y4m_fill_buffer(demuxer_t
*demux
, demux_stream_t
*dsds
) {
84 demux_stream_t
*ds
=demux
->video
;
86 y4m_priv_t
*priv
=demux
->priv
;
88 unsigned char *buf
[3];
92 // Concatenated stream check; only done if seekable so skip(-1) works
93 if (demux
->stream
->flags
& MP_STREAM_SEEK_BW
) {
94 nextc
= stream_read_char(demux
->stream
);
95 stream_skip(demux
->stream
, -1);
97 read_streaminfo(demux
);
102 y4m_init_frame_info(&fi
);
104 demux
->filepos
=stream_tell(demux
->stream
);
106 size
= ((sh_video_t
*)ds
->sh
)->disp_w
*((sh_video_t
*)ds
->sh
)->disp_h
;
108 dp
= new_demux_packet(3*size
/2);
110 /* swap U and V components */
112 buf
[1] = dp
->buffer
+ 5*size
/4;
113 buf
[2] = dp
->buffer
+ size
;
119 c
= stream_read_char(demux
->stream
); /* F */
124 mp_msg(MSGT_DEMUX
, MSGL_V
, "Bad frame at %d\n", (int)stream_tell(demux
->stream
)-1);
127 stream_skip(demux
->stream
, 5); /* RAME\n */
128 stream_read(demux
->stream
, buf
[0], size
);
129 stream_read(demux
->stream
, buf
[1], size
/4);
130 stream_read(demux
->stream
, buf
[2], size
/4);
134 if ((err
=y4m_read_frame(demux
->stream
, priv
->si
, &fi
, buf
)) != Y4M_OK
) {
135 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "error reading frame %s\n", y4m_strerr(err
));
140 /* This seems to be the right way to calculate the presentation time stamp */
141 dp
->pts
=(float)priv
->framenum
/((sh_video_t
*)ds
->sh
)->fps
;
143 dp
->pos
=demux
->filepos
;
145 ds_add_packet(ds
, dp
);
150 static void read_streaminfo(demuxer_t
*demuxer
)
152 y4m_priv_t
*priv
= demuxer
->priv
;
153 sh_video_t
*sh
= demuxer
->video
->sh
;
162 stream_skip(demuxer
->stream
, 8); /* YUV4MPEG */
163 stream_skip(demuxer
->stream
, 1); /* space */
164 stream_read(demuxer
->stream
, (char *)&buf
[0], 3);
166 sh
->disp_w
= atoi(buf
);
167 stream_skip(demuxer
->stream
, 1); /* space */
168 stream_read(demuxer
->stream
, (char *)&buf
[0], 3);
170 sh
->disp_h
= atoi(buf
);
171 stream_skip(demuxer
->stream
, 1); /* space */
172 stream_read(demuxer
->stream
, (char *)&buf
[0], 1);
174 frame_rate_code
= atoi(buf
);
175 stream_skip(demuxer
->stream
, 1); /* new-line */
179 /* values from xawtv */
180 switch(frame_rate_code
)
210 sh
->frametime
= 1.0f
/sh
->fps
;
214 y4m_init_stream_info(priv
->si
);
215 if ((err
=y4m_read_stream_header(demuxer
->stream
, priv
->si
)) != Y4M_OK
)
216 mp_msg(MSGT_DEMUXER
, MSGL_FATAL
, "error parsing YUV4MPEG header: %s\n", y4m_strerr(err
));
219 ratio
= y4m_si_get_framerate(priv
->si
);
221 sh
->fps
=(float)ratio
.n
/(float)ratio
.d
;
225 sh
->frametime
=1.0f
/sh
->fps
;
227 ratio
= y4m_si_get_sampleaspect(priv
->si
);
229 sh
->disp_w
= y4m_si_get_width(priv
->si
);
230 sh
->disp_h
= y4m_si_get_height(priv
->si
);
232 if (ratio
.d
!= 0 && ratio
.n
!= 0)
233 sh
->aspect
= (float)(sh
->disp_w
*ratio
.n
)/(float)(sh
->disp_h
*ratio
.d
);
235 demuxer
->seekable
= 0;
238 sh
->format
= mmioFOURCC('Y', 'V', '1', '2');
241 sh
->bih
->biWidth
= sh
->disp_w
;
242 sh
->bih
->biHeight
= sh
->disp_h
;
244 sh
->bih
->biBitCount
=12;
245 sh
->bih
->biCompression
=sh
->format
;
246 sh
->bih
->biSizeImage
=sh
->bih
->biWidth
*sh
->bih
->biHeight
*3/2; /* YV12 */
248 mp_msg(MSGT_DEMUX
, MSGL_INFO
, "YUV4MPEG2 Video stream %d size: display: %dx%d, codec: %ux%u\n",
249 demuxer
->video
->id
, sh
->disp_w
, sh
->disp_h
, sh
->bih
->biWidth
,
253 static demuxer_t
* demux_open_y4m(demuxer_t
* demuxer
){
254 y4m_priv_t
* priv
= demuxer
->priv
;
255 sh_video_t
* sh
=new_sh_video(demuxer
,0);
258 priv
->si
= malloc(sizeof(y4m_stream_info_t
));
260 sh
->bih
=calloc(1, sizeof(BITMAPINFOHEADER
));
262 demuxer
->video
->sh
=sh
;
263 sh
->ds
=demuxer
->video
;
264 demuxer
->video
->id
=0;
266 read_streaminfo(demuxer
);
271 static void demux_seek_y4m(demuxer_t
*demuxer
, float rel_seek_secs
, float audio_delay
, int flags
) {
272 sh_video_t
* sh
= demuxer
->video
->sh
;
273 y4m_priv_t
* priv
= demuxer
->priv
;
274 int rel_seek_frames
= sh
->fps
*rel_seek_secs
;
275 int size
= 3*sh
->disp_w
*sh
->disp_h
/2;
276 off_t curr_pos
= stream_tell(demuxer
->stream
);
278 if (priv
->framenum
+ rel_seek_frames
< 0) rel_seek_frames
= -priv
->framenum
;
280 //printf("seektoframe=%d rel_seek_secs=%f seektooffset=%ld\n", priv->framenum + rel_seek_frames, rel_seek_secs, curr_pos + rel_seek_frames*(size+6));
281 //printf("framenum=%d, curr_pos=%ld, currpos/(size+6)=%f\n", priv->framenum, curr_pos, (float)curr_pos/(float)(size+6));
282 priv
->framenum
+= rel_seek_frames
;
284 if (priv
->is_older
) {
285 /* Well this is easy: every frame takes up size+6 bytes
286 * in the stream and we may assume that the stream pointer
287 * is always at the beginning of a frame.
288 * framenum is the number of the frame that is about to be
289 * demuxed (counting from ONE (see demux_open_y4m)) */
290 stream_seek(demuxer
->stream
, curr_pos
+ rel_seek_frames
*(size
+6));
292 /* should never come here, because seeking for YUV4MPEG2
294 mp_msg(MSGT_DEMUX
, MSGL_WARN
, "Seeking for YUV4MPEG2 not yet implemented!\n");
298 static void demux_close_y4m(demuxer_t
*demuxer
)
300 y4m_priv_t
* priv
= demuxer
->priv
;
305 y4m_fini_stream_info(((y4m_priv_t
*)demuxer
->priv
)->si
);
306 free(((y4m_priv_t
*)demuxer
->priv
)->si
);
312 const demuxer_desc_t demuxer_desc_y4m
= {
319 1, // safe autodetect
321 demux_y4m_fill_buffer
,