1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2015 VLC authors and VideoLAN
7 * Authors: Denis Charmet <typx@videolan.org>
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 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_codec.h>
35 #include <vlc_block.h>
37 #include "../codec/avcodec/avcodec.h"
38 #include "../codec/avcodec/avcommon.h"
41 /*****************************************************************************
43 *****************************************************************************/
50 /*****************************************************************************
52 *****************************************************************************/
55 AVCodecParserContext
* p_parser_ctx
;
56 AVCodecContext
* p_codec_ctx
;
60 static block_t
* Packetize( decoder_t
*, block_t
** );
61 static block_t
* PacketizeClosed( decoder_t
*, block_t
** );
63 /*****************************************************************************
64 * FlushPacketizer: reopen as there's no clean way to flush avparser
65 *****************************************************************************/
66 static void FlushPacketizer( decoder_t
*p_dec
)
68 ClosePacketizer( VLC_OBJECT( p_dec
) );
70 int res
= OpenPacketizer( VLC_OBJECT( p_dec
) );
71 if ( res
!= VLC_SUCCESS
)
73 msg_Err( p_dec
, "failed to flush with error %d", res
);
74 p_dec
->pf_packetize
= PacketizeClosed
;
78 /*****************************************************************************
79 * OpenPacketizer: probe the packetizer and return score
80 *****************************************************************************
81 * Tries to launch a decoder and return score so that the interface is able
83 *****************************************************************************/
84 int OpenPacketizer( vlc_object_t
*p_this
)
86 decoder_t
*p_dec
= (decoder_t
*)p_this
;
89 /* Restrict to VP9 for now */
90 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_VP9
)
93 unsigned i_avcodec_id
;
95 if( !GetFfmpegCodec( p_dec
->fmt_in
.i_cat
, p_dec
->fmt_in
.i_codec
,
96 &i_avcodec_id
, NULL
) )
100 vlc_init_avcodec(p_this
);
102 /* It is less likely to have a parser than a codec, start by that */
103 AVCodecParserContext
* p_ctx
= av_parser_init( i_avcodec_id
);
107 AVCodec
* p_codec
= avcodec_find_decoder( i_avcodec_id
);
108 if( unlikely( !p_codec
) )
110 av_parser_close( p_ctx
);
114 AVCodecContext
* p_codec_ctx
= avcodec_alloc_context3( p_codec
);
115 if( unlikely( !p_codec_ctx
) )
117 av_parser_close( p_ctx
);
121 p_dec
->p_sys
= p_sys
= malloc( sizeof(*p_sys
) );
123 if( unlikely( !p_sys
) )
125 avcodec_free_context( &p_codec_ctx
);
126 av_parser_close( p_ctx
);
129 p_dec
->pf_packetize
= Packetize
;
130 p_dec
->pf_flush
= FlushPacketizer
;
131 p_sys
->p_parser_ctx
= p_ctx
;
132 p_sys
->p_codec_ctx
= p_codec_ctx
;
134 es_format_Copy( &p_dec
->fmt_out
, &p_dec
->fmt_in
);
139 /*****************************************************************************
141 *****************************************************************************/
142 void ClosePacketizer( vlc_object_t
*p_this
)
144 decoder_t
*p_dec
= (decoder_t
*)p_this
;
145 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
146 if (likely( p_sys
!= NULL
))
148 avcodec_free_context( &p_sys
->p_codec_ctx
);
149 av_parser_close( p_sys
->p_parser_ctx
);
154 /*****************************************************************************
155 * Packetize: packetize a frame
156 *****************************************************************************/
157 static block_t
*Packetize ( decoder_t
*p_dec
, block_t
**pp_block
)
159 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
161 if( pp_block
== NULL
|| *pp_block
== NULL
)
163 if( (*pp_block
)->i_flags
&(BLOCK_FLAG_CORRUPTED
) )
165 block_Release( *pp_block
);
169 block_t
* p_block
= *pp_block
;
171 uint8_t * p_indata
= p_block
->p_buffer
+ p_sys
->i_offset
;
172 int i_inlen
= p_block
->i_buffer
- p_sys
->i_offset
;
176 if( p_sys
->i_offset
== i_inlen
)
179 p_sys
->i_offset
+= av_parser_parse2( p_sys
->p_parser_ctx
, p_sys
->p_codec_ctx
,
180 &p_outdata
, &i_outlen
, p_indata
, i_inlen
,
181 p_block
->i_pts
, p_block
->i_dts
, -1);
183 if( unlikely( i_outlen
<= 0 || !p_outdata
) )
186 block_t
* p_ret
= block_Alloc( i_outlen
);
188 if( unlikely ( !p_ret
) )
191 memcpy( p_ret
->p_buffer
, p_outdata
, i_outlen
);
192 p_ret
->i_pts
= p_block
->i_pts
;
193 p_ret
->i_dts
= p_block
->i_dts
;
194 if( p_sys
->p_parser_ctx
->key_frame
== 1 )
195 p_ret
->i_flags
|= BLOCK_FLAG_TYPE_I
;
197 p_block
->i_pts
= p_block
->i_dts
= VLC_TS_INVALID
;
203 block_Release( *pp_block
);
208 /*****************************************************************************
209 * PacketizeClosed: packetizer called after a flush failed
210 *****************************************************************************/
211 static block_t
*PacketizeClosed ( decoder_t
*p_dec
, block_t
**pp_block
)
214 if( pp_block
!= NULL
&& *pp_block
!= NULL
)
215 block_Release( *pp_block
);