3 * copyright (c) 2002 Alexander Neundorf <neundorf@kde.org>
4 * based on the fli demuxer
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with MPlayer; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
31 #include "stream/stream.h"
36 #include <libdv/dv_types.h>
38 #define DV_PAL_FRAME_SIZE 144000
39 #define DV_NTSC_FRAME_SIZE 122000
45 off_t current_filepos
;
47 dv_decoder_t
*decoder
;
50 static void demux_seek_rawdv(demuxer_t
*demuxer
,float rel_seek_secs
,float audio_delay
,int flags
)
52 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
53 sh_video_t
*sh_video
= demuxer
->video
->sh
;
54 off_t newpos
=(flags
&SEEK_ABSOLUTE
)?0:frames
->current_frame
;
58 newpos
+=rel_seek_secs
*frames
->frame_number
;
63 newpos
+=rel_seek_secs
*sh_video
->fps
;
67 else if(newpos
>frames
->frame_number
)
68 newpos
=frames
->frame_number
;
69 frames
->current_frame
=newpos
;
70 frames
->current_filepos
=newpos
*frames
->frame_size
;
73 static int rawdv_check_file(demuxer_t
*demuxer
)
75 unsigned char tmp_buffer
[DV_PAL_FRAME_SIZE
];
80 mp_msg(MSGT_DEMUX
,MSGL_V
,"Checking for DV\n");
82 bytes_read
=stream_read(demuxer
->stream
,tmp_buffer
,DV_PAL_FRAME_SIZE
);
83 if ((bytes_read
!=DV_PAL_FRAME_SIZE
) && (bytes_read
!=DV_NTSC_FRAME_SIZE
))
86 td
=dv_decoder_new(TRUE
,TRUE
,FALSE
);
90 td
->quality
=DV_QUALITY_BEST
;
91 result
=dv_parse_header(td
, tmp_buffer
);
95 if ((( td
->num_dif_seqs
==10) || (td
->num_dif_seqs
==12))
97 && ((td
->height
==576) || (td
->height
==480)))
101 return DEMUXER_TYPE_RAWDV
;
107 // 0 = EOF or no stream found
108 // 1 = successfully read a packet
109 static int demux_rawdv_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
)
111 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
112 demux_packet_t
* dp_video
=NULL
;
113 sh_video_t
*sh_video
= demuxer
->video
->sh
;
115 // fprintf(stderr,"demux_rawdv_fill_buffer() seek to %qu, size: %d\n",frames->current_filepos,frames->frame_size);
116 // fetch the frame from the file
117 // first, position the file properly since ds_read_packet() doesn't
118 // seem to do it, even though it takes a file offset as a parameter
119 stream_seek(demuxer
->stream
, frames
->current_filepos
);
121 dp_video
=new_demux_packet(frames
->frame_size
);
122 bytes_read
=stream_read(demuxer
->stream
,dp_video
->buffer
,frames
->frame_size
);
123 if (bytes_read
<frames
->frame_size
)
125 dp_video
->pts
=frames
->current_frame
/sh_video
->fps
;
126 dp_video
->pos
=frames
->current_filepos
;
129 if (demuxer
->audio
&& demuxer
->audio
->id
>=-1)
131 demux_packet_t
* dp_audio
=clone_demux_packet(dp_video
);
132 ds_add_packet(demuxer
->audio
,dp_audio
);
134 ds_add_packet(demuxer
->video
,dp_video
);
135 // get the next frame ready
136 frames
->current_filepos
+=frames
->frame_size
;
137 frames
->current_frame
++;
138 // fprintf(stderr," audio->packs: %d , video->packs: %d \n",demuxer->audio->packs, demuxer->video->packs);
142 static demuxer_t
* demux_open_rawdv(demuxer_t
* demuxer
)
144 unsigned char dv_frame
[DV_PAL_FRAME_SIZE
];
145 sh_video_t
*sh_video
= NULL
;
146 rawdv_frames_t
*frames
= malloc(sizeof(rawdv_frames_t
));
147 dv_decoder_t
*dv_decoder
=NULL
;
149 mp_msg(MSGT_DEMUXER
,MSGL_V
,"demux_open_rawdv() end_pos %"PRId64
"\n",(int64_t)demuxer
->stream
->end_pos
);
151 // go back to the beginning
152 stream_reset(demuxer
->stream
);
153 stream_seek(demuxer
->stream
, 0);
155 //get the first frame
156 stream_read(demuxer
->stream
, dv_frame
, DV_PAL_FRAME_SIZE
);
158 //read params from this frame
159 dv_decoder
=dv_decoder_new(TRUE
,TRUE
,FALSE
);
160 dv_decoder
->quality
=DV_QUALITY_BEST
;
162 if (dv_parse_header(dv_decoder
, dv_frame
) == -1)
165 // create a new video stream header
166 sh_video
= new_sh_video(demuxer
, 0);
170 // make sure the demuxer knows about the new video stream header
171 // (even though new_sh_video() ought to take care of it)
172 demuxer
->seekable
= 1;
173 demuxer
->video
->sh
= sh_video
;
175 // make sure that the video demuxer stream header knows about its
176 // parent video demuxer stream (this is getting wacky), or else
177 // video_read_properties() will choke
178 sh_video
->ds
= demuxer
->video
;
180 // custom fourcc for internal MPlayer use
181 // sh_video->format = mmioFOURCC('R', 'A', 'D', 'V');
182 sh_video
->format
= mmioFOURCC('D', 'V', 'S', 'D');
184 sh_video
->disp_w
= dv_decoder
->width
;
185 sh_video
->disp_h
= dv_decoder
->height
;
186 mp_msg(MSGT_DEMUXER
,MSGL_V
,"demux_open_rawdv() frame_size: %d w: %d h: %d dif_seq: %d system: %d\n",dv_decoder
->frame_size
,dv_decoder
->width
, dv_decoder
->height
,dv_decoder
->num_dif_seqs
,dv_decoder
->system
);
188 sh_video
->fps
= (dv_decoder
->system
==e_dv_system_525_60
?29.97:25);
189 sh_video
->frametime
= 1.0/sh_video
->fps
;
191 // emulate BITMAPINFOHEADER for win32 decoders:
192 sh_video
->bih
=calloc(1, sizeof(*sh_video
->bih
));
193 sh_video
->bih
->biSize
=40;
194 sh_video
->bih
->biWidth
= dv_decoder
->width
;
195 sh_video
->bih
->biHeight
= dv_decoder
->height
;
196 sh_video
->bih
->biPlanes
=1;
197 sh_video
->bih
->biBitCount
=24;
198 sh_video
->bih
->biCompression
=sh_video
->format
; // "DVSD"
199 sh_video
->bih
->biSizeImage
=sh_video
->bih
->biWidth
*sh_video
->bih
->biHeight
*3;
202 frames
->current_filepos
=0;
203 frames
->current_frame
=0;
204 frames
->frame_size
=dv_decoder
->frame_size
;
205 frames
->frame_number
=demuxer
->stream
->end_pos
/frames
->frame_size
;
207 mp_msg(MSGT_DEMUXER
,MSGL_V
,"demux_open_rawdv() seek to %qu, size: %d, dv_dec->frame_size: %d\n",frames
->current_filepos
,frames
->frame_size
, dv_decoder
->frame_size
);
208 if (dv_decoder
->audio
!= NULL
&& demuxer
->audio
->id
>=-1){
209 sh_audio_t
*sh_audio
= new_sh_audio(demuxer
, 0);
210 demuxer
->audio
->id
= 0;
211 demuxer
->audio
->sh
= sh_audio
;
212 sh_audio
->ds
= demuxer
->audio
;
213 mp_msg(MSGT_DEMUXER
,MSGL_V
,"demux_open_rawdv() chan: %d samplerate: %d\n",dv_decoder
->audio
->num_channels
,dv_decoder
->audio
->frequency
);
214 // custom fourcc for internal MPlayer use
215 sh_audio
->format
= mmioFOURCC('R', 'A', 'D', 'V');
217 sh_audio
->wf
= calloc(1, sizeof(*sh_audio
->wf
));
218 sh_audio
->wf
->wFormatTag
= sh_audio
->format
;
219 sh_audio
->wf
->nChannels
= dv_decoder
->audio
->num_channels
;
220 sh_audio
->wf
->wBitsPerSample
= 16;
221 sh_audio
->wf
->nSamplesPerSec
= dv_decoder
->audio
->frequency
;
222 // info about the input stream:
223 sh_audio
->wf
->nAvgBytesPerSec
= sh_video
->fps
*dv_decoder
->frame_size
;
224 sh_audio
->wf
->nBlockAlign
= dv_decoder
->frame_size
;
226 // sh_audio->context=(void*)dv_decoder;
228 stream_reset(demuxer
->stream
);
229 stream_seek(demuxer
->stream
, 0);
230 dv_decoder_free(dv_decoder
); //we keep this in the context of both stream headers
231 demuxer
->priv
=frames
;
235 static void demux_close_rawdv(demuxer_t
* demuxer
)
237 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
244 static int demux_rawdv_control(demuxer_t
*demuxer
,int cmd
, void *arg
) {
245 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
246 sh_video_t
*sh_video
=demuxer
->video
->sh
;
249 case DEMUXER_CTRL_GET_TIME_LENGTH
:
250 *((double *)arg
)=(double)frames
->frame_number
/ sh_video
->fps
;
251 return DEMUXER_CTRL_OK
;
253 case DEMUXER_CTRL_GET_PERCENT_POS
:
254 *((int *)arg
)=(int)(frames
->current_frame
* 100. / frames
->frame_number
);
255 return DEMUXER_CTRL_OK
;
258 return DEMUXER_CTRL_NOTIMPL
;
263 const demuxer_desc_t demuxer_desc_rawdv
= {
267 "Alexander Neundorf",
270 0, // unsafe autodetect
272 demux_rawdv_fill_buffer
,