macOS vout: fix forgotten ';'
[vlc.git] / modules / packetizer / avparser.c
bloba9c864e25bdd3d51fcb4afc7f76a87edfedcfebe
1 /*****************************************************************************
2 * avparser.c
3 *****************************************************************************
4 * Copyright (C) 2015 VLC authors and VideoLAN
5 * $Id$
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 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
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"
40 #include "avparser.h"
41 /*****************************************************************************
42 * Module descriptor
43 *****************************************************************************/
44 #ifndef MERGE_FFMPEG
45 vlc_module_begin ()
46 AVPARSER_MODULE
47 vlc_module_end ()
48 #endif
50 /*****************************************************************************
51 * Local prototypes
52 *****************************************************************************/
53 typedef struct
55 AVCodecParserContext * p_parser_ctx;
56 AVCodecContext * p_codec_ctx;
57 int i_offset;
58 } decoder_sys_t;
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 ) );
69 p_dec->p_sys = NULL;
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
82 * to choose.
83 *****************************************************************************/
84 int OpenPacketizer( vlc_object_t *p_this )
86 decoder_t *p_dec = (decoder_t*)p_this;
87 decoder_sys_t *p_sys;
89 /* Restrict to VP9 for now */
90 if( p_dec->fmt_in.i_codec != VLC_CODEC_VP9 )
91 return VLC_EGENERIC;
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 ) )
97 return VLC_EGENERIC;
99 /* init avcodec */
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 );
104 if( !p_ctx )
105 return VLC_EGENERIC;
107 AVCodec * p_codec = avcodec_find_decoder( i_avcodec_id );
108 if( unlikely( !p_codec ) )
110 av_parser_close( p_ctx );
111 return VLC_EGENERIC;
114 AVCodecContext * p_codec_ctx = avcodec_alloc_context3( p_codec );
115 if( unlikely( !p_codec_ctx ) )
117 av_parser_close( p_ctx );
118 return VLC_ENOMEM;
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 );
127 return VLC_ENOMEM;
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;
133 p_sys->i_offset = 0;
134 es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
136 return VLC_SUCCESS;
139 /*****************************************************************************
140 * ClosePacketizer:
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 );
150 free( p_sys );
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 )
162 return NULL;
163 if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) )
165 block_Release( *pp_block );
166 return NULL;
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;
173 uint8_t * p_outdata;
174 int i_outlen;
176 if( p_sys->i_offset == i_inlen )
177 goto out;
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 ) )
184 goto out;
186 block_t * p_ret = block_Alloc( i_outlen );
188 if( unlikely ( !p_ret ) )
189 goto out;
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;
199 return p_ret;
201 out:
202 p_sys->i_offset = 0;
203 block_Release( *pp_block );
204 *pp_block = NULL;
205 return NULL;
208 /*****************************************************************************
209 * PacketizeClosed: packetizer called after a flush failed
210 *****************************************************************************/
211 static block_t *PacketizeClosed ( decoder_t *p_dec, block_t **pp_block )
213 (void) p_dec;
214 if( pp_block != NULL && *pp_block != NULL )
215 block_Release( *pp_block );
216 return NULL;