1 /*****************************************************************************
2 * mash.c: Video decoder using openmash codec implementations
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
7 * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
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; either version 2 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 General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, 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>
34 #include <vlc_block.h>
38 /*****************************************************************************
39 * decoder_sys_t : video decoder descriptor
40 *****************************************************************************/
47 IntraP64Decoder
*p_decoder
;
53 /****************************************************************************
55 ****************************************************************************/
56 static int OpenDecoder ( vlc_object_t
* );
57 static void CloseDecoder ( vlc_object_t
* );
59 static void *DecodeBlock ( decoder_t
*, block_t
** );
62 static picture_t
*DecodeFrame( decoder_t
*, block_t
* );
63 static block_t
*SendFrame ( decoder_t
*, block_t
* );
66 /*****************************************************************************
68 *****************************************************************************/
70 set_description( N_("Video decoder using openmash") )
71 set_capability( "decoder", 50 )
72 set_category( CAT_INPUT
)
73 set_subcategory( SUBCAT_INPUT_VCODEC
)
74 set_callbacks( OpenDecoder
, CloseDecoder
)
77 /*****************************************************************************
78 * OpenDecoder: probe the decoder and return score
79 *****************************************************************************/
80 static int OpenDecoder( vlc_object_t
*p_this
)
82 decoder_t
*p_dec
= (decoder_t
*)p_this
;
85 switch( p_dec
->fmt_in
.i_codec
)
95 /* Allocate the memory needed to store the decoder's structure */
96 if( ( p_dec
->p_sys
= p_sys
=
97 (decoder_sys_t
*)malloc(sizeof(decoder_sys_t
)) ) == NULL
)
100 p_sys
->i_pts
= VLC_TS_INVALID
;
101 p_sys
->b_inited
= false;
102 p_sys
->i_counter
= 0;
104 /* Set output properties */
105 p_dec
->fmt_out
.i_cat
= VIDEO_ES
;
106 p_dec
->fmt_out
.i_codec
= VLC_CODEC_I420
;
109 p_dec
->pf_decode_video
= (picture_t
*(*)(decoder_t
*, block_t
**))
111 p_sys
->p_decoder
= new IntraP64Decoder();
117 /*****************************************************************************
118 * CloseDecoder: decoder destruction
119 *****************************************************************************/
120 static void CloseDecoder( vlc_object_t
*p_this
)
122 decoder_t
*p_dec
= (decoder_t
*)p_this
;
123 free( p_dec
->p_sys
);
127 /****************************************************************************
128 * DecodeBlock: the whole thing
129 ****************************************************************************
130 * This function must be fed with complete frames.
131 ****************************************************************************/
132 static void *DecodeBlock( decoder_t
*p_dec
, block_t
**pp_block
)
134 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
137 uint32_t i_video_header
;
139 int cc
, sbit
, ebit
, mba
, gob
, quant
, mvdh
, mvdv
;
140 int i_width
, i_height
;
142 if( !pp_block
|| !*pp_block
) return NULL
;
146 if( p_sys
->i_pts
<= VLC_TS_INVALID
&& p_block
->i_pts
<= VLC_TS_INVALID
&&
147 p_block
->i_dts
<= VLC_TS_INVALID
)
149 /* We've just started the stream, wait for the first PTS. */
150 block_Release( p_block
);
155 /* Date management */
156 if( p_block
->i_pts
> VLC_TS_INVALID
)
157 p_sys
->i_pts
= p_block
->i_pts
;
158 else if( p_block
->i_dts
> VLC_TS_INVALID
)
159 p_sys
->i_pts
= p_block
->i_dts
;
161 i_video_header
= *(uint32_t*)p_block
->p_buffer
; /* yes, it is native endian */
162 sbit
= i_video_header
>> 29; /* start bit position */
163 ebit
= (i_video_header
>> 26) & 7; /* end bit position */
164 msg_Dbg( p_dec
, "sbit, ebit: %d,%d", sbit
, ebit
);
165 gob
= (i_video_header
>> 20) & 0xf; /* GOB number */
168 msg_Warn( p_dec
, "invalid gob, buggy vic streamer?");
170 mba
= (i_video_header
>> 15) & 0x1f; /* Macroblock address predictor */
171 quant
= (i_video_header
>> 10) & 0x1f; /* quantizer */
172 mvdh
= (i_video_header
>> 5) & 0x1f; /* horizontal motion vector data */
173 mvdv
= i_video_header
& 0x1f; /* vertical motion vector data */
174 cc
= p_block
->i_buffer
- 4;
175 msg_Dbg( p_dec
, "packet size %d", cc
);
177 /* Find out p_vdec->i_raw_size */
178 p_sys
->p_decoder
->decode( p_block
->p_buffer
+ 4 /*bp?*/,
187 i_width
= p_sys
->p_decoder
->width();
188 i_height
= p_sys
->p_decoder
->height();
189 if( !p_sys
->b_inited
)
191 msg_Dbg( p_dec
, "video size is perhaps %dx%d", i_width
,
193 video_format_Setup( &p_dec
->fmt_out
.video
, VLC_CODEC_I420
,
196 p_sys
->b_inited
= true;
200 // p_sys->p_decoder->sync();
201 if( p_block
->i_flags
& BLOCK_FLAG_END_OF_FRAME
)
203 p_pic
= decoder_NewPicture( p_dec
);
206 block_Release( p_block
);
209 p_sys
->p_decoder
->sync();
210 p_sys
->i_counter
= 0;
211 p_frame
= p_sys
->p_decoder
->frame();
212 vlc_memcpy( p_dec
, p_pic
->p
[0].p_pixels
, p_frame
, i_width
*i_height
);
213 p_frame
+= i_width
* i_height
;
214 vlc_memcpy( p_dec
, p_pic
->p
[1].p_pixels
, p_frame
, i_width
*i_height
/4 );
215 p_frame
+= i_width
* i_height
/4;
216 vlc_memcpy( p_dec
, p_pic
->p
[2].p_pixels
, p_frame
, i_width
*i_height
/4 );
217 p_pic
->date
= p_sys
->i_pts
;
219 block_Release( p_block
);