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 *****************************************************************************/
46 unsigned pitches
[PICTURE_PLANE_MAX
];
47 unsigned lines
[PICTURE_PLANE_MAX
];
55 /****************************************************************************
57 ****************************************************************************/
58 static int OpenDecoder ( vlc_object_t
* );
59 static int OpenPacketizer( vlc_object_t
* );
60 static void CloseCommon ( vlc_object_t
* );
62 /*****************************************************************************
64 *****************************************************************************/
66 set_description( N_("Pseudo raw video decoder") )
67 set_capability( "decoder", 50 )
68 set_category( CAT_INPUT
)
69 set_subcategory( SUBCAT_INPUT_VCODEC
)
70 set_callbacks( OpenDecoder
, CloseCommon
)
73 set_description( N_("Pseudo raw video packetizer") )
74 set_capability( "packetizer", 100 )
75 set_callbacks( OpenPacketizer
, CloseCommon
)
79 * Common initialization for decoder and packetizer
81 static int OpenCommon( decoder_t
*p_dec
)
83 const vlc_chroma_description_t
*dsc
=
84 vlc_fourcc_GetChromaDescription( p_dec
->fmt_in
.i_codec
);
85 if( dsc
== NULL
|| dsc
->plane_count
== 0 )
88 if( p_dec
->fmt_in
.video
.i_width
<= 0 || p_dec
->fmt_in
.video
.i_height
== 0 )
90 msg_Err( p_dec
, "invalid display size %dx%d",
91 p_dec
->fmt_in
.video
.i_width
, p_dec
->fmt_in
.video
.i_height
);
95 /* Allocate the memory needed to store the decoder's structure */
96 decoder_sys_t
*p_sys
= calloc(1, sizeof(*p_sys
));
97 if( unlikely(p_sys
== NULL
) )
100 if( (int)p_dec
->fmt_in
.video
.i_height
< 0 )
102 /* Frames are coded from bottom to top */
103 p_dec
->fmt_in
.video
.i_height
=
104 (unsigned int)(-(int)p_dec
->fmt_in
.video
.i_height
);
105 p_sys
->b_invert
= true;
107 if( !p_dec
->fmt_in
.video
.i_visible_width
)
108 p_dec
->fmt_in
.video
.i_visible_width
= p_dec
->fmt_in
.video
.i_width
;
109 if( !p_dec
->fmt_in
.video
.i_visible_height
)
110 p_dec
->fmt_in
.video
.i_visible_height
= p_dec
->fmt_in
.video
.i_height
;
112 es_format_Copy( &p_dec
->fmt_out
, &p_dec
->fmt_in
);
114 date_Init( &p_sys
->pts
, p_dec
->fmt_out
.video
.i_frame_rate
,
115 p_dec
->fmt_out
.video
.i_frame_rate_base
);
116 if( p_dec
->fmt_out
.video
.i_frame_rate
== 0 ||
117 p_dec
->fmt_out
.video
.i_frame_rate_base
== 0)
119 msg_Warn( p_dec
, "invalid frame rate %d/%d, using 25 fps instead",
120 p_dec
->fmt_out
.video
.i_frame_rate
,
121 p_dec
->fmt_out
.video
.i_frame_rate_base
);
122 date_Init( &p_sys
->pts
, 25, 1 );
125 for( unsigned i
= 0; i
< dsc
->plane_count
; i
++ )
127 unsigned pitch
= p_dec
->fmt_in
.video
.i_width
* dsc
->pixel_size
128 * dsc
->p
[i
].w
.num
/ dsc
->p
[i
].w
.den
;
129 unsigned lines
= p_dec
->fmt_in
.video
.i_height
130 * dsc
->p
[i
].h
.num
/ dsc
->p
[i
].h
.den
;
132 p_sys
->pitches
[i
] = pitch
;
133 p_sys
->lines
[i
] = lines
;
134 p_sys
->size
+= pitch
* lines
;
137 p_dec
->p_sys
= p_sys
;
141 /****************************************************************************
142 * DecodeBlock: the whole thing
143 ****************************************************************************
144 * This function must be fed with complete frames.
145 ****************************************************************************/
146 static void *DecodeBlock( decoder_t
*p_dec
, block_t
**pp_block
)
148 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
150 if( pp_block
== NULL
|| *pp_block
== NULL
)
153 block_t
*p_block
= *pp_block
;
155 if( p_block
->i_pts
<= VLC_TS_INVALID
&& p_block
->i_dts
<= VLC_TS_INVALID
&&
156 !date_Get( &p_sys
->pts
) )
158 /* We've just started the stream, wait for the first PTS. */
159 block_Release( p_block
);
163 /* Date management: If there is a pts avaliable, use that. */
164 if( p_block
->i_pts
> VLC_TS_INVALID
)
166 date_Set( &p_sys
->pts
, p_block
->i_pts
);
168 else if( p_block
->i_dts
> VLC_TS_INVALID
)
170 /* NB, davidf doesn't quite agree with this in general, it is ok
171 * for rawvideo since it is in order (ie pts=dts), however, it
172 * may not be ok for an out-of-order codec, so don't copy this
173 * without thinking */
174 date_Set( &p_sys
->pts
, p_block
->i_dts
);
177 if( p_block
->i_buffer
< p_sys
->size
)
179 msg_Warn( p_dec
, "invalid frame size (%zu < %zu)",
180 p_block
->i_buffer
, p_sys
->size
);
182 block_Release( p_block
);
190 /*****************************************************************************
192 *****************************************************************************/
193 static void FillPicture( decoder_t
*p_dec
, block_t
*p_block
, picture_t
*p_pic
)
195 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
196 const uint8_t *p_src
= p_block
->p_buffer
;
198 if( p_sys
->b_invert
)
199 for( int i
= 0; i
< p_pic
->i_planes
; i
++ )
201 uint8_t *p_dst
= p_pic
->p
[i
].p_pixels
202 + (p_pic
->p
[i
].i_pitch
* p_pic
->p
[i
].i_visible_lines
);
204 for( int x
= 0; x
< p_pic
->p
[i
].i_visible_lines
; x
++ )
206 p_dst
-= p_pic
->p
[i
].i_pitch
;
207 memcpy( p_dst
, p_src
, p_pic
->p
[i
].i_visible_pitch
);
208 p_src
+= p_sys
->pitches
[i
];
211 p_src
+= p_sys
->pitches
[i
]
212 * (p_sys
->lines
[i
] - p_pic
->p
[i
].i_visible_lines
);
215 for( int i
= 0; i
< p_pic
->i_planes
; i
++ )
217 uint8_t *p_dst
= p_pic
->p
[i
].p_pixels
;
219 for( int x
= 0; x
< p_pic
->p
[i
].i_visible_lines
; x
++ )
221 memcpy( p_dst
, p_src
, p_pic
->p
[i
].i_visible_pitch
);
222 p_src
+= p_sys
->pitches
[i
];
223 p_dst
+= p_pic
->p
[i
].i_pitch
;
226 p_src
+= p_sys
->pitches
[i
]
227 * (p_sys
->lines
[i
] - p_pic
->p
[i
].i_visible_lines
);
231 /*****************************************************************************
232 * DecodeFrame: decodes a video frame.
233 *****************************************************************************/
234 static picture_t
*DecodeFrame( decoder_t
*p_dec
, block_t
**pp_block
)
236 block_t
*p_block
= DecodeBlock( p_dec
, pp_block
);
237 if( p_block
== NULL
)
240 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
242 /* Get a new picture */
243 picture_t
*p_pic
= decoder_NewPicture( p_dec
);
246 block_Release( p_block
);
250 FillPicture( p_dec
, p_block
, p_pic
);
252 /* Date management: 1 frame per packet */
253 p_pic
->date
= date_Get( &p_dec
->p_sys
->pts
);
254 date_Increment( &p_sys
->pts
, 1 );
256 if( p_block
->i_flags
& BLOCK_FLAG_INTERLACED_MASK
)
258 p_pic
->b_progressive
= false;
259 p_pic
->i_nb_fields
= 2;
260 if( p_block
->i_flags
& BLOCK_FLAG_TOP_FIELD_FIRST
)
261 p_pic
->b_top_field_first
= true;
263 p_pic
->b_top_field_first
= false;
266 p_pic
->b_progressive
= true;
268 block_Release( p_block
);
272 static int OpenDecoder( vlc_object_t
*p_this
)
274 decoder_t
*p_dec
= (decoder_t
*)p_this
;
276 int ret
= OpenCommon( p_dec
);
277 if( ret
== VLC_SUCCESS
)
278 p_dec
->pf_decode_video
= DecodeFrame
;
282 /*****************************************************************************
283 * SendFrame: send a video frame to the stream output.
284 *****************************************************************************/
285 static block_t
*SendFrame( decoder_t
*p_dec
, block_t
**pp_block
)
287 block_t
*p_block
= DecodeBlock( p_dec
, pp_block
);
288 if( p_block
== NULL
)
291 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
293 /* Date management: 1 frame per packet */
294 p_block
->i_dts
= p_block
->i_pts
= date_Get( &p_sys
->pts
);
295 date_Increment( &p_sys
->pts
, 1 );
297 if( p_sys
->b_invert
)
299 block_t
*out
= block_Alloc( p_block
->i_buffer
);
300 if( likely(out
!= NULL
) )
302 block_CopyProperties( out
, p_block
);
304 const uint8_t *p_src
= p_block
->p_buffer
;
305 uint8_t *p_pixels
= out
->p_buffer
;
307 for( unsigned i
= 0; i
< PICTURE_PLANE_MAX
; i
++ )
309 unsigned pitch
= p_sys
->pitches
[i
];
310 unsigned lines
= p_sys
->lines
[i
];
311 uint8_t *p_dst
= p_pixels
+ (pitch
* lines
);
313 for( unsigned x
= 0; x
< lines
; x
++ )
315 p_dst
-= p_sys
->pitches
[i
];
316 memcpy( p_dst
, p_src
, p_sys
->pitches
[i
] );
317 p_src
+= p_sys
->pitches
[i
];
321 block_Release( p_block
);
328 static int OpenPacketizer( vlc_object_t
*p_this
)
330 decoder_t
*p_dec
= (decoder_t
*)p_this
;
332 int ret
= OpenCommon( p_dec
);
333 if( ret
== VLC_SUCCESS
)
334 p_dec
->pf_packetize
= SendFrame
;
339 * Common deinitialization
341 static void CloseCommon( vlc_object_t
*p_this
)
343 decoder_t
*p_dec
= (decoder_t
*)p_this
;
344 free( p_dec
->p_sys
);