1 /*****************************************************************************
2 * rawvideo.c: Pseudo video decoder/packetizer for raw video data
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VLC authors and VideoLAN
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
35 /*****************************************************************************
36 * decoder_sys_t : raw video decoder descriptor
37 *****************************************************************************/
44 unsigned pitches
[PICTURE_PLANE_MAX
];
45 unsigned lines
[PICTURE_PLANE_MAX
];
53 /****************************************************************************
55 ****************************************************************************/
56 static int OpenDecoder ( vlc_object_t
* );
57 static int OpenPacketizer( vlc_object_t
* );
58 static void CloseCommon ( vlc_object_t
* );
60 /*****************************************************************************
62 *****************************************************************************/
64 set_description( N_("Pseudo raw video decoder") )
65 set_capability( "decoder", 50 )
66 set_category( CAT_INPUT
)
67 set_subcategory( SUBCAT_INPUT_VCODEC
)
68 set_callbacks( OpenDecoder
, CloseCommon
)
71 set_description( N_("Pseudo raw video packetizer") )
72 set_capability( "packetizer", 100 )
73 set_callbacks( OpenPacketizer
, CloseCommon
)
77 * Common initialization for decoder and packetizer
79 static int OpenCommon( decoder_t
*p_dec
)
81 const vlc_chroma_description_t
*dsc
=
82 vlc_fourcc_GetChromaDescription( p_dec
->fmt_in
.i_codec
);
83 if( dsc
== NULL
|| dsc
->plane_count
== 0 )
86 if( p_dec
->fmt_in
.video
.i_width
<= 0 || p_dec
->fmt_in
.video
.i_height
== 0 )
88 msg_Err( p_dec
, "invalid display size %dx%d",
89 p_dec
->fmt_in
.video
.i_width
, p_dec
->fmt_in
.video
.i_height
);
93 /* Allocate the memory needed to store the decoder's structure */
94 decoder_sys_t
*p_sys
= calloc(1, sizeof(*p_sys
));
95 if( unlikely(p_sys
== NULL
) )
98 if( !p_dec
->fmt_in
.video
.i_visible_width
)
99 p_dec
->fmt_in
.video
.i_visible_width
= p_dec
->fmt_in
.video
.i_width
;
100 if( !p_dec
->fmt_in
.video
.i_visible_height
)
101 p_dec
->fmt_in
.video
.i_visible_height
= p_dec
->fmt_in
.video
.i_height
;
103 es_format_Copy( &p_dec
->fmt_out
, &p_dec
->fmt_in
);
105 date_Init( &p_sys
->pts
, p_dec
->fmt_out
.video
.i_frame_rate
,
106 p_dec
->fmt_out
.video
.i_frame_rate_base
);
107 if( p_dec
->fmt_out
.video
.i_frame_rate
== 0 ||
108 p_dec
->fmt_out
.video
.i_frame_rate_base
== 0)
110 msg_Warn( p_dec
, "invalid frame rate %d/%d, using 25 fps instead",
111 p_dec
->fmt_out
.video
.i_frame_rate
,
112 p_dec
->fmt_out
.video
.i_frame_rate_base
);
113 date_Init( &p_sys
->pts
, 25, 1 );
116 for( unsigned i
= 0; i
< dsc
->plane_count
; i
++ )
118 unsigned pitch
= p_dec
->fmt_in
.video
.i_width
* dsc
->pixel_size
119 * dsc
->p
[i
].w
.num
/ dsc
->p
[i
].w
.den
;
120 unsigned lines
= p_dec
->fmt_in
.video
.i_height
121 * dsc
->p
[i
].h
.num
/ dsc
->p
[i
].h
.den
;
123 p_sys
->pitches
[i
] = pitch
;
124 p_sys
->lines
[i
] = lines
;
125 p_sys
->size
+= pitch
* lines
;
128 p_dec
->p_sys
= p_sys
;
132 /*****************************************************************************
134 *****************************************************************************/
135 static void Flush( decoder_t
*p_dec
)
137 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
139 date_Set( &p_sys
->pts
, VLC_TS_INVALID
);
142 /****************************************************************************
143 * DecodeBlock: the whole thing
144 ****************************************************************************
145 * This function must be fed with complete frames.
146 ****************************************************************************/
147 static void *DecodeBlock( decoder_t
*p_dec
, block_t
**pp_block
)
149 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
151 if( pp_block
== NULL
|| *pp_block
== NULL
)
154 block_t
*p_block
= *pp_block
;
156 if( p_block
->i_flags
& BLOCK_FLAG_DISCONTINUITY
)
157 date_Set( &p_sys
->pts
, p_block
->i_dts
);
159 if( p_block
->i_pts
<= VLC_TS_INVALID
&& p_block
->i_dts
<= VLC_TS_INVALID
&&
160 !date_Get( &p_sys
->pts
) )
162 /* We've just started the stream, wait for the first PTS. */
163 block_Release( p_block
);
167 /* Date management: If there is a pts avaliable, use that. */
168 if( p_block
->i_pts
> VLC_TS_INVALID
)
170 date_Set( &p_sys
->pts
, p_block
->i_pts
);
172 else if( p_block
->i_dts
> VLC_TS_INVALID
)
174 /* NB, davidf doesn't quite agree with this in general, it is ok
175 * for rawvideo since it is in order (ie pts=dts), however, it
176 * may not be ok for an out-of-order codec, so don't copy this
177 * without thinking */
178 date_Set( &p_sys
->pts
, p_block
->i_dts
);
181 if( p_block
->i_buffer
< p_sys
->size
)
183 msg_Warn( p_dec
, "invalid frame size (%zu < %zu)",
184 p_block
->i_buffer
, p_sys
->size
);
186 block_Release( p_block
);
194 /*****************************************************************************
196 *****************************************************************************/
197 static void FillPicture( decoder_t
*p_dec
, block_t
*p_block
, picture_t
*p_pic
)
199 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
200 const uint8_t *p_src
= p_block
->p_buffer
;
202 for( int i
= 0; i
< p_pic
->i_planes
; i
++ )
204 uint8_t *p_dst
= p_pic
->p
[i
].p_pixels
;
206 for( int x
= 0; x
< p_pic
->p
[i
].i_visible_lines
; x
++ )
208 memcpy( p_dst
, p_src
, p_pic
->p
[i
].i_visible_pitch
);
209 p_src
+= p_sys
->pitches
[i
];
210 p_dst
+= p_pic
->p
[i
].i_pitch
;
213 p_src
+= p_sys
->pitches
[i
]
214 * (p_sys
->lines
[i
] - p_pic
->p
[i
].i_visible_lines
);
218 /*****************************************************************************
219 * DecodeFrame: decodes a video frame.
220 *****************************************************************************/
221 static picture_t
*DecodeFrame( decoder_t
*p_dec
, block_t
**pp_block
)
223 block_t
*p_block
= DecodeBlock( p_dec
, pp_block
);
224 if( p_block
== NULL
)
227 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
229 /* Get a new picture */
230 picture_t
*p_pic
= NULL
;
231 if( !decoder_UpdateVideoFormat( p_dec
) )
232 p_pic
= decoder_NewPicture( p_dec
);
235 block_Release( p_block
);
239 FillPicture( p_dec
, p_block
, p_pic
);
241 /* Date management: 1 frame per packet */
242 p_pic
->date
= date_Get( &p_dec
->p_sys
->pts
);
243 date_Increment( &p_sys
->pts
, 1 );
245 if( p_block
->i_flags
& BLOCK_FLAG_INTERLACED_MASK
)
247 p_pic
->b_progressive
= false;
248 p_pic
->i_nb_fields
= 2;
249 if( p_block
->i_flags
& BLOCK_FLAG_TOP_FIELD_FIRST
)
250 p_pic
->b_top_field_first
= true;
252 p_pic
->b_top_field_first
= false;
255 p_pic
->b_progressive
= true;
257 block_Release( p_block
);
261 static int OpenDecoder( vlc_object_t
*p_this
)
263 decoder_t
*p_dec
= (decoder_t
*)p_this
;
265 int ret
= OpenCommon( p_dec
);
266 if( ret
== VLC_SUCCESS
)
268 p_dec
->pf_decode_video
= DecodeFrame
;
269 p_dec
->pf_flush
= Flush
;
274 /*****************************************************************************
275 * SendFrame: send a video frame to the stream output.
276 *****************************************************************************/
277 static block_t
*SendFrame( decoder_t
*p_dec
, block_t
**pp_block
)
279 block_t
*p_block
= DecodeBlock( p_dec
, pp_block
);
280 if( p_block
== NULL
)
283 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
285 /* Date management: 1 frame per packet */
286 p_block
->i_dts
= p_block
->i_pts
= date_Get( &p_sys
->pts
);
287 date_Increment( &p_sys
->pts
, 1 );
291 static int OpenPacketizer( vlc_object_t
*p_this
)
293 decoder_t
*p_dec
= (decoder_t
*)p_this
;
295 int ret
= OpenCommon( p_dec
);
296 if( ret
== VLC_SUCCESS
)
297 p_dec
->pf_packetize
= SendFrame
;
302 * Common deinitialization
304 static void CloseCommon( vlc_object_t
*p_this
)
306 decoder_t
*p_dec
= (decoder_t
*)p_this
;
307 free( p_dec
->p_sys
);