1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * Media source implementation that reads DV frames from raw DV files.
5 * This file is part of monster
7 * Copyright (C) 2006,2007 Nedko Arnaudov <nedko@arnaudov.name>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License
13 * This program 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
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 *****************************************************************************/
24 #include <sys/types.h>
32 #define DISABLE_DEBUG_OUTPUT
35 #include "media_source.h"
36 #include "media_source_dv.h"
41 struct media_source_dv
43 struct media_source
virtual;
46 unsigned int frame_size
;
47 void * frame_buffer_ptr
;
54 #define media_source_ptr ((struct media_source_dv *)virtual_ptr)
56 void media_source_dv_destroy(struct media_source
* virtual_ptr
)
58 DEBUG_OUT("media_source_dv_destroy");
59 close(media_source_ptr
->file_handle
);
60 free(media_source_ptr
->frame_buffer_ptr
);
61 free(media_source_ptr
);
64 int media_source_dv_format_query(struct media_source
* virtual_ptr
, unsigned int * format_ptr
)
66 DEBUG_OUT("media_source_dv_format_query");
67 *format_ptr
= media_source_ptr
->format
;
71 int media_source_dv_get_frame_data(struct media_source
* virtual_ptr
, void ** buffer_ptr_ptr
)
73 DEBUG_OUT("media_source_dv_get_frame_data");
75 if (media_source_ptr
->error
< 0)
77 return media_source_ptr
->error
;
80 *buffer_ptr_ptr
= media_source_ptr
->frame_buffer_ptr
;
82 return media_source_ptr
->eof
? 1 : 0;
86 media_source_dv_next_frame(struct media_source
* virtual_ptr
)
90 DEBUG_OUT("media_source_dv_next_frame");
92 if (media_source_ptr
->error
< 0)
97 if (media_source_ptr
->initial_counter
== 0)
99 media_source_ptr
->initial_counter
++;
100 // memset(media_source_ptr->frame_buffer_ptr, 0, media_source_ptr->frame_size);
103 else if (media_source_ptr
->initial_counter
< media_source_ptr
->initial_repeat
)
105 media_source_ptr
->initial_counter
++;
109 ssret
= read(media_source_ptr
->file_handle
, media_source_ptr
->frame_buffer_ptr
, media_source_ptr
->frame_size
);
110 if (ssret
!= media_source_ptr
->frame_size
)
114 ERROR_OUT("cannot read the raw DV file (%d)", errno
);
115 media_source_ptr
->error
= -1;
119 ERROR_OUT("only %u bytes read from the raw DV file instead of %u", (unsigned int)ssret
, media_source_ptr
->frame_size
);
120 media_source_ptr
->error
= -1;
124 DEBUG_OUT("no more data");
125 media_source_ptr
->eof
= true;
130 #undef media_source_ptr
134 const char * filename
,
135 struct media_source
** media_source_ptr_ptr
)
137 struct media_source_dv
* media_source_ptr
;
143 unsigned int frame_size
;
145 unsigned int calibration_frames
;
147 DEBUG_OUT("media_source_dv");
149 ret
= conf_file_get_uint("/conf/video/calibration_frames", &calibration_frames
);
152 ERROR_OUT("failed to read from configuration how many calibration frames to use");
157 file_handle
= open(filename
, O_LARGEFILE
);
158 if (file_handle
== -1)
160 ERROR_OUT("cannot open \"%s\" (%d)", filename
, errno
);
165 if (fstat(file_handle
, &st
) == -1)
167 ERROR_OUT("cannot fstat \"%s\" (%d)", filename
, errno
);
169 goto exit_close_handle
;
174 ERROR_OUT("\"%s\" is too small", filename
);
176 goto exit_close_handle
;
180 ssret
= read(file_handle
, data
, 4);
185 ERROR_OUT("cannot read \"%s\" (%d)", filename
, errno
);
189 ERROR_OUT("only %u bytes read from \"%s\" instead of 4", (unsigned int)ssret
, filename
);
192 goto exit_close_handle
;
195 if ((data
[0] >> 5) != 0 || /* first dif block should be header section */
196 (data
[3] & 0x40) != 0) /* this bit must be for DV files */
198 ERROR_OUT("\"%s\" is not in raw DV format (header check)", filename
);
200 goto exit_close_handle
;
203 if ((data
[3] & 0x80) != 0)
205 DEBUG_OUT("625/50 (PAL)");
206 format
= MEDIA_FORMAT_DV_PAL
;
207 frame_size
= DV_FRAME_SIZE_PAL
;
208 NOTICE_OUT("Video: Using %u calibration frames (%f seconds)", calibration_frames
, (float)calibration_frames
/25.0);
212 DEBUG_OUT("525/60 (NTSC)");
213 format
= MEDIA_FORMAT_DV_NTSC
;
214 frame_size
= DV_FRAME_SIZE_NTSC
;
215 NOTICE_OUT("Video: Using %u calibration frames (%f seconds)", calibration_frames
, (float)calibration_frames
/29.97);
218 if (st
.st_size
% frame_size
!= 0)
220 ERROR_OUT("\"%s\" is not in raw DV format (size check)", filename
);
222 goto exit_close_handle
;
226 if (lseek(file_handle
, 0, SEEK_SET
) != 0)
228 ERROR_OUT("\"%s\" rewind failed", filename
);
230 goto exit_close_handle
;
233 media_source_ptr
= (struct media_source_dv
*)malloc(sizeof(struct media_source_dv
));
234 if (media_source_ptr
== NULL
)
236 ERROR_OUT("malloc() failed.");
238 goto exit_close_handle
;
241 media_source_ptr
->frame_buffer_ptr
= malloc(frame_size
);
242 if (media_source_ptr
->frame_buffer_ptr
== NULL
)
244 ERROR_OUT("malloc() failed.");
249 media_source_ptr
->virtual.destroy
= media_source_dv_destroy
;
250 media_source_ptr
->virtual.format_query
= media_source_dv_format_query
;
251 media_source_ptr
->virtual.get_frame_data
= media_source_dv_get_frame_data
;
252 media_source_ptr
->virtual.next_frame
= media_source_dv_next_frame
;
254 media_source_ptr
->file_handle
= file_handle
;
255 media_source_ptr
->format
= format
;
256 media_source_ptr
->frame_size
= frame_size
;
258 media_source_ptr
->error
= 0;
259 media_source_ptr
->eof
= false;
260 media_source_ptr
->initial_counter
= 0;
261 media_source_ptr
->initial_repeat
= calibration_frames
;
262 media_source_dv_next_frame(&media_source_ptr
->virtual);
264 if (media_source_ptr
->error
< 0)
266 ret
= media_source_ptr
->error
;
267 goto exit_free_frame_data
;
270 *media_source_ptr_ptr
= &media_source_ptr
->virtual;
275 exit_free_frame_data
:
276 free(media_source_ptr
->frame_buffer_ptr
);
279 free(media_source_ptr
);