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
32 #include "stream/stream.h"
37 #include <libdv/dv_types.h>
39 #define DV_PAL_FRAME_SIZE 144000
40 #define DV_NTSC_FRAME_SIZE 122000
46 off_t current_filepos
;
48 dv_decoder_t
*decoder
;
51 static void demux_seek_rawdv(demuxer_t
*demuxer
,float rel_seek_secs
,float audio_delay
,int flags
)
53 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
54 sh_video_t
*sh_video
= demuxer
->video
->sh
;
55 off_t newpos
=(flags
&SEEK_ABSOLUTE
)?0:frames
->current_frame
;
59 newpos
+=rel_seek_secs
*frames
->frame_number
;
64 newpos
+=rel_seek_secs
*sh_video
->fps
;
68 else if(newpos
>frames
->frame_number
)
69 newpos
=frames
->frame_number
;
70 frames
->current_frame
=newpos
;
71 frames
->current_filepos
=newpos
*frames
->frame_size
;
74 static int rawdv_check_file(demuxer_t
*demuxer
)
76 unsigned char tmp_buffer
[DV_PAL_FRAME_SIZE
];
81 mp_msg(MSGT_DEMUX
,MSGL_V
,"Checking for DV\n");
83 bytes_read
=stream_read(demuxer
->stream
,tmp_buffer
,DV_PAL_FRAME_SIZE
);
84 if ((bytes_read
!=DV_PAL_FRAME_SIZE
) && (bytes_read
!=DV_NTSC_FRAME_SIZE
))
87 td
=dv_decoder_new(TRUE
,TRUE
,FALSE
);
91 td
->quality
=DV_QUALITY_BEST
;
92 result
=dv_parse_header(td
, tmp_buffer
);
96 if ((( td
->num_dif_seqs
==10) || (td
->num_dif_seqs
==12))
98 && ((td
->height
==576) || (td
->height
==480)))
102 return DEMUXER_TYPE_RAWDV
;
108 // 0 = EOF or no stream found
109 // 1 = successfully read a packet
110 static int demux_rawdv_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
)
112 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
113 demux_packet_t
* dp_video
=NULL
;
114 sh_video_t
*sh_video
= demuxer
->video
->sh
;
116 // fprintf(stderr,"demux_rawdv_fill_buffer() seek to %qu, size: %d\n",frames->current_filepos,frames->frame_size);
117 // fetch the frame from the file
118 // first, position the file properly since ds_read_packet() doesn't
119 // seem to do it, even though it takes a file offset as a parameter
120 stream_seek(demuxer
->stream
, frames
->current_filepos
);
122 dp_video
=new_demux_packet(frames
->frame_size
);
123 bytes_read
=stream_read(demuxer
->stream
,dp_video
->buffer
,frames
->frame_size
);
124 if (bytes_read
<frames
->frame_size
)
126 dp_video
->pts
=frames
->current_frame
/sh_video
->fps
;
127 dp_video
->pos
=frames
->current_filepos
;
130 if (demuxer
->audio
&& demuxer
->audio
->id
>=-1)
132 demux_packet_t
* dp_audio
=clone_demux_packet(dp_video
);
133 ds_add_packet(demuxer
->audio
,dp_audio
);
135 ds_add_packet(demuxer
->video
,dp_video
);
136 // get the next frame ready
137 frames
->current_filepos
+=frames
->frame_size
;
138 frames
->current_frame
++;
139 // fprintf(stderr," audio->packs: %d , video->packs: %d \n",demuxer->audio->packs, demuxer->video->packs);
143 static demuxer_t
* demux_open_rawdv(demuxer_t
* demuxer
)
145 unsigned char dv_frame
[DV_PAL_FRAME_SIZE
];
146 sh_video_t
*sh_video
= NULL
;
147 rawdv_frames_t
*frames
= malloc(sizeof(rawdv_frames_t
));
148 dv_decoder_t
*dv_decoder
=NULL
;
150 mp_msg(MSGT_DEMUXER
,MSGL_V
,"demux_open_rawdv() end_pos %"PRId64
"\n",(int64_t)demuxer
->stream
->end_pos
);
152 // go back to the beginning
153 stream_reset(demuxer
->stream
);
154 stream_seek(demuxer
->stream
, 0);
156 //get the first frame
157 stream_read(demuxer
->stream
, dv_frame
, DV_PAL_FRAME_SIZE
);
159 //read params from this frame
160 dv_decoder
=dv_decoder_new(TRUE
,TRUE
,FALSE
);
161 dv_decoder
->quality
=DV_QUALITY_BEST
;
163 if (dv_parse_header(dv_decoder
, dv_frame
) == -1)
166 // create a new video stream header
167 sh_video
= new_sh_video(demuxer
, 0);
171 // make sure the demuxer knows about the new video stream header
172 // (even though new_sh_video() ought to take care of it)
173 demuxer
->seekable
= 1;
174 demuxer
->video
->sh
= sh_video
;
176 // make sure that the video demuxer stream header knows about its
177 // parent video demuxer stream (this is getting wacky), or else
178 // video_read_properties() will choke
179 sh_video
->ds
= demuxer
->video
;
181 // custom fourcc for internal MPlayer use
182 // sh_video->format = mmioFOURCC('R', 'A', 'D', 'V');
183 sh_video
->format
= mmioFOURCC('D', 'V', 'S', 'D');
185 sh_video
->disp_w
= dv_decoder
->width
;
186 sh_video
->disp_h
= dv_decoder
->height
;
187 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
);
189 sh_video
->fps
= (dv_decoder
->system
==e_dv_system_525_60
?29.97:25);
190 sh_video
->frametime
= 1.0/sh_video
->fps
;
192 // emulate BITMAPINFOHEADER for win32 decoders:
193 sh_video
->bih
=malloc(sizeof(BITMAPINFOHEADER
));
194 memset(sh_video
->bih
,0,sizeof(BITMAPINFOHEADER
));
195 sh_video
->bih
->biSize
=40;
196 sh_video
->bih
->biWidth
= dv_decoder
->width
;
197 sh_video
->bih
->biHeight
= dv_decoder
->height
;
198 sh_video
->bih
->biPlanes
=1;
199 sh_video
->bih
->biBitCount
=24;
200 sh_video
->bih
->biCompression
=sh_video
->format
; // "DVSD"
201 sh_video
->bih
->biSizeImage
=sh_video
->bih
->biWidth
*sh_video
->bih
->biHeight
*3;
204 frames
->current_filepos
=0;
205 frames
->current_frame
=0;
206 frames
->frame_size
=dv_decoder
->frame_size
;
207 frames
->frame_number
=demuxer
->stream
->end_pos
/frames
->frame_size
;
209 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
);
210 if (dv_decoder
->audio
!= NULL
&& demuxer
->audio
->id
>=-1){
211 sh_audio_t
*sh_audio
= new_sh_audio(demuxer
, 0);
212 demuxer
->audio
->id
= 0;
213 demuxer
->audio
->sh
= sh_audio
;
214 sh_audio
->ds
= demuxer
->audio
;
215 mp_msg(MSGT_DEMUXER
,MSGL_V
,"demux_open_rawdv() chan: %d samplerate: %d\n",dv_decoder
->audio
->num_channels
,dv_decoder
->audio
->frequency
);
216 // custom fourcc for internal MPlayer use
217 sh_audio
->format
= mmioFOURCC('R', 'A', 'D', 'V');
219 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
220 memset(sh_audio
->wf
, 0, sizeof(WAVEFORMATEX
));
221 sh_audio
->wf
->wFormatTag
= sh_audio
->format
;
222 sh_audio
->wf
->nChannels
= dv_decoder
->audio
->num_channels
;
223 sh_audio
->wf
->wBitsPerSample
= 16;
224 sh_audio
->wf
->nSamplesPerSec
= dv_decoder
->audio
->frequency
;
225 // info about the input stream:
226 sh_audio
->wf
->nAvgBytesPerSec
= sh_video
->fps
*dv_decoder
->frame_size
;
227 sh_audio
->wf
->nBlockAlign
= dv_decoder
->frame_size
;
229 // sh_audio->context=(void*)dv_decoder;
231 stream_reset(demuxer
->stream
);
232 stream_seek(demuxer
->stream
, 0);
233 dv_decoder_free(dv_decoder
); //we keep this in the context of both stream headers
234 demuxer
->priv
=frames
;
238 static void demux_close_rawdv(demuxer_t
* demuxer
)
240 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
247 static int demux_rawdv_control(demuxer_t
*demuxer
,int cmd
, void *arg
) {
248 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
249 sh_video_t
*sh_video
=demuxer
->video
->sh
;
252 case DEMUXER_CTRL_GET_TIME_LENGTH
:
253 *((double *)arg
)=(double)frames
->frame_number
/ sh_video
->fps
;
254 return DEMUXER_CTRL_OK
;
256 case DEMUXER_CTRL_GET_PERCENT_POS
:
257 *((int *)arg
)=(int)(frames
->current_frame
* 100. / frames
->frame_number
);
258 return DEMUXER_CTRL_OK
;
261 return DEMUXER_CTRL_NOTIMPL
;
266 const demuxer_desc_t demuxer_desc_rawdv
= {
270 "Alexander Neundorf",
273 0, // unsafe autodetect
275 demux_rawdv_fill_buffer
,