2 raw dv file parser for MPlayer
3 by Alexander Neundorf <neundorf@kde.org>
4 based on the fli demuxer
18 #include "stream/stream.h"
23 #include <libdv/dv_types.h>
25 #define DV_PAL_FRAME_SIZE 144000
26 #define DV_NTSC_FRAME_SIZE 122000
32 off_t current_filepos
;
34 dv_decoder_t
*decoder
;
37 static void demux_seek_rawdv(demuxer_t
*demuxer
,float rel_seek_secs
,float audio_delay
,int flags
)
39 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
40 sh_video_t
*sh_video
= demuxer
->video
->sh
;
41 off_t newpos
=(flags
&1)?0:frames
->current_frame
;
45 newpos
+=rel_seek_secs
*frames
->frame_number
;
50 newpos
+=rel_seek_secs
*sh_video
->fps
;
54 else if(newpos
>frames
->frame_number
)
55 newpos
=frames
->frame_number
;
56 frames
->current_frame
=newpos
;
57 frames
->current_filepos
=newpos
*frames
->frame_size
;
60 static int rawdv_check_file(demuxer_t
*demuxer
)
62 unsigned char tmp_buffer
[DV_PAL_FRAME_SIZE
];
67 mp_msg(MSGT_DEMUX
,MSGL_V
,"Checking for DV\n");
69 bytes_read
=stream_read(demuxer
->stream
,tmp_buffer
,DV_PAL_FRAME_SIZE
);
70 if ((bytes_read
!=DV_PAL_FRAME_SIZE
) && (bytes_read
!=DV_NTSC_FRAME_SIZE
))
73 td
=dv_decoder_new(TRUE
,TRUE
,FALSE
);
77 td
->quality
=DV_QUALITY_BEST
;
78 result
=dv_parse_header(td
, tmp_buffer
);
82 if ((( td
->num_dif_seqs
==10) || (td
->num_dif_seqs
==12))
84 && ((td
->height
==576) || (td
->height
==480)))
88 return DEMUXER_TYPE_RAWDV
;
94 // 0 = EOF or no stream found
95 // 1 = successfully read a packet
96 static int demux_rawdv_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
)
98 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
99 demux_packet_t
* dp_video
=NULL
;
100 sh_video_t
*sh_video
= demuxer
->video
->sh
;
102 // fprintf(stderr,"demux_rawdv_fill_buffer() seek to %qu, size: %d\n",frames->current_filepos,frames->frame_size);
103 // fetch the frame from the file
104 // first, position the file properly since ds_read_packet() doesn't
105 // seem to do it, even though it takes a file offset as a parameter
106 stream_seek(demuxer
->stream
, frames
->current_filepos
);
108 dp_video
=new_demux_packet(frames
->frame_size
);
109 bytes_read
=stream_read(demuxer
->stream
,dp_video
->buffer
,frames
->frame_size
);
110 if (bytes_read
<frames
->frame_size
)
112 dp_video
->pts
=frames
->current_frame
/sh_video
->fps
;
113 dp_video
->pos
=frames
->current_filepos
;
116 if (demuxer
->audio
&& demuxer
->audio
->id
>=-1)
118 demux_packet_t
* dp_audio
=clone_demux_packet(dp_video
);
119 ds_add_packet(demuxer
->audio
,dp_audio
);
121 ds_add_packet(demuxer
->video
,dp_video
);
122 // get the next frame ready
123 frames
->current_filepos
+=frames
->frame_size
;
124 frames
->current_frame
++;
125 // fprintf(stderr," audio->packs: %d , video->packs: %d \n",demuxer->audio->packs, demuxer->video->packs);
129 static demuxer_t
* demux_open_rawdv(demuxer_t
* demuxer
)
131 unsigned char dv_frame
[DV_PAL_FRAME_SIZE
];
132 sh_video_t
*sh_video
= NULL
;
133 rawdv_frames_t
*frames
= malloc(sizeof(rawdv_frames_t
));
134 dv_decoder_t
*dv_decoder
=NULL
;
136 mp_msg(MSGT_DEMUXER
,MSGL_V
,"demux_open_rawdv() end_pos %"PRId64
"\n",(int64_t)demuxer
->stream
->end_pos
);
138 // go back to the beginning
139 stream_reset(demuxer
->stream
);
140 stream_seek(demuxer
->stream
, 0);
142 //get the first frame
143 stream_read(demuxer
->stream
, dv_frame
, DV_PAL_FRAME_SIZE
);
145 //read params from this frame
146 dv_decoder
=dv_decoder_new(TRUE
,TRUE
,FALSE
);
147 dv_decoder
->quality
=DV_QUALITY_BEST
;
149 if (dv_parse_header(dv_decoder
, dv_frame
) == -1)
152 // create a new video stream header
153 sh_video
= new_sh_video(demuxer
, 0);
157 // make sure the demuxer knows about the new video stream header
158 // (even though new_sh_video() ought to take care of it)
159 demuxer
->seekable
= 1;
160 demuxer
->video
->sh
= sh_video
;
162 // make sure that the video demuxer stream header knows about its
163 // parent video demuxer stream (this is getting wacky), or else
164 // video_read_properties() will choke
165 sh_video
->ds
= demuxer
->video
;
167 // custom fourcc for internal MPlayer use
168 // sh_video->format = mmioFOURCC('R', 'A', 'D', 'V');
169 sh_video
->format
= mmioFOURCC('D', 'V', 'S', 'D');
171 sh_video
->disp_w
= dv_decoder
->width
;
172 sh_video
->disp_h
= dv_decoder
->height
;
173 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
);
175 sh_video
->fps
= (dv_decoder
->system
==e_dv_system_525_60
?29.97:25);
176 sh_video
->frametime
= 1.0/sh_video
->fps
;
178 // emulate BITMAPINFOHEADER for win32 decoders:
179 sh_video
->bih
=malloc(sizeof(BITMAPINFOHEADER
));
180 memset(sh_video
->bih
,0,sizeof(BITMAPINFOHEADER
));
181 sh_video
->bih
->biSize
=40;
182 sh_video
->bih
->biWidth
= dv_decoder
->width
;
183 sh_video
->bih
->biHeight
= dv_decoder
->height
;
184 sh_video
->bih
->biPlanes
=1;
185 sh_video
->bih
->biBitCount
=24;
186 sh_video
->bih
->biCompression
=sh_video
->format
; // "DVSD"
187 sh_video
->bih
->biSizeImage
=sh_video
->bih
->biWidth
*sh_video
->bih
->biHeight
*3;
190 frames
->current_filepos
=0;
191 frames
->current_frame
=0;
192 frames
->frame_size
=dv_decoder
->frame_size
;
193 frames
->frame_number
=demuxer
->stream
->end_pos
/frames
->frame_size
;
195 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
);
196 if (dv_decoder
->audio
!= NULL
&& demuxer
->audio
->id
>=-1){
197 sh_audio_t
*sh_audio
= new_sh_audio(demuxer
, 0);
198 demuxer
->audio
->sh
= sh_audio
;
199 sh_audio
->ds
= demuxer
->audio
;
200 mp_msg(MSGT_DEMUXER
,MSGL_V
,"demux_open_rawdv() chan: %d samplerate: %d\n",dv_decoder
->audio
->num_channels
,dv_decoder
->audio
->frequency
);
201 // custom fourcc for internal MPlayer use
202 sh_audio
->format
= mmioFOURCC('R', 'A', 'D', 'V');
204 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
205 memset(sh_audio
->wf
, 0, sizeof(WAVEFORMATEX
));
206 sh_audio
->wf
->wFormatTag
= sh_audio
->format
;
207 sh_audio
->wf
->nChannels
= dv_decoder
->audio
->num_channels
;
208 sh_audio
->wf
->wBitsPerSample
= 16;
209 sh_audio
->wf
->nSamplesPerSec
= dv_decoder
->audio
->frequency
;
210 // info about the input stream:
211 sh_audio
->wf
->nAvgBytesPerSec
= sh_video
->fps
*dv_decoder
->frame_size
;
212 sh_audio
->wf
->nBlockAlign
= dv_decoder
->frame_size
;
214 // sh_audio->context=(void*)dv_decoder;
216 stream_reset(demuxer
->stream
);
217 stream_seek(demuxer
->stream
, 0);
218 dv_decoder_free(dv_decoder
); //we keep this in the context of both stream headers
219 demuxer
->priv
=frames
;
223 static void demux_close_rawdv(demuxer_t
* demuxer
)
225 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
232 static int demux_rawdv_control(demuxer_t
*demuxer
,int cmd
, void *arg
) {
233 rawdv_frames_t
*frames
= (rawdv_frames_t
*)demuxer
->priv
;
234 sh_video_t
*sh_video
=demuxer
->video
->sh
;
237 case DEMUXER_CTRL_GET_TIME_LENGTH
:
238 *((double *)arg
)=(double)frames
->frame_number
/ sh_video
->fps
;
239 return DEMUXER_CTRL_OK
;
241 case DEMUXER_CTRL_GET_PERCENT_POS
:
242 *((int *)arg
)=(int)(frames
->current_frame
* 100. / frames
->frame_number
);
243 return DEMUXER_CTRL_OK
;
246 return DEMUXER_CTRL_NOTIMPL
;
251 demuxer_desc_t demuxer_desc_rawdv
= {
255 "Alexander Neundorf",
258 0, // unsafe autodetect
260 demux_rawdv_fill_buffer
,