demux: heif: send extradata with avif
[vlc.git] / modules / stream_out / stats.c
blob05beb069662d40f3c2cbc532eaabbb013530d416
1 /*****************************************************************************
2 * delay.c: delay a stream
3 *****************************************************************************
4 * Copyright © 2014 VLC authors and VideoLAN
6 * Authors: Ilkka Ollakka <ileoo at videolan dot org>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
24 * Preamble
25 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_sout.h>
33 #include <vlc_block.h>
34 #include <vlc_md5.h>
35 #include <vlc_fs.h>
37 /*****************************************************************************
38 * Module descriptor
39 *****************************************************************************/
40 #define OUTPUT_TEXT N_("Output file")
41 #define OUTPUT_LONGTEXT N_( \
42 "Writes stats to file instead of stdout" )
43 #define PREFIX_TEXT N_("Prefix to show on output line")
45 static int Open ( vlc_object_t * );
46 static void Close ( vlc_object_t * );
48 #define SOUT_CFG_PREFIX "sout-stats-"
50 vlc_module_begin()
51 set_shortname( N_("Stats"))
52 set_description( N_("Writes statistic info about stream"))
53 set_capability( "sout stream", 0 )
54 add_shortcut( "stats" )
55 set_category( CAT_SOUT )
56 set_subcategory( SUBCAT_SOUT_STREAM )
57 set_callbacks( Open, Close )
58 add_string( SOUT_CFG_PREFIX "output", "", OUTPUT_TEXT,OUTPUT_LONGTEXT, false );
59 add_string( SOUT_CFG_PREFIX "prefix", "stats", PREFIX_TEXT,PREFIX_TEXT, false );
60 vlc_module_end()
63 /*****************************************************************************
64 * Local prototypes
65 *****************************************************************************/
66 static const char *ppsz_sout_options[] = {
67 "output", "prefix", NULL
70 static void *Add( sout_stream_t *, const es_format_t * );
71 static void Del( sout_stream_t *, void * );
72 static int Send( sout_stream_t *, void *, block_t * );
74 typedef struct
76 FILE *output;
77 char *prefix;
78 } sout_stream_sys_t;
80 typedef struct
82 int id;
83 uint64_t segment_number;
84 void *next_id;
85 const char *type;
86 vlc_tick_t previous_dts,track_duration;
87 struct md5_s hash;
88 } sout_stream_id_sys_t;
90 /*****************************************************************************
91 * Open:
92 *****************************************************************************/
93 static int Open( vlc_object_t *p_this )
95 sout_stream_t *p_stream = (sout_stream_t*)p_this;
96 sout_stream_sys_t *p_sys;
97 char *outputFile;
99 p_sys = calloc( 1, sizeof( sout_stream_sys_t ) );
100 if( !p_sys )
101 return VLC_ENOMEM;
104 config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
105 p_stream->p_cfg );
108 outputFile = var_InheritString( p_stream, SOUT_CFG_PREFIX "output" );
110 if( outputFile )
112 p_sys->output = vlc_fopen( outputFile, "wt" );
113 if( !p_sys->output )
115 msg_Err( p_stream, "Unable to open file '%s' for writing", outputFile );
116 free( p_sys );
117 free( outputFile );
118 return VLC_EGENERIC;
119 } else {
120 fprintf( p_sys->output,"#prefix\ttrack\ttype\tsegment_number\tdts_difference\tlength\tmd5\n");
122 free( outputFile );
124 p_sys->prefix = var_InheritString( p_stream, SOUT_CFG_PREFIX "prefix" );
126 p_stream->p_sys = p_sys;
128 p_stream->pf_add = Add;
129 p_stream->pf_del = Del;
130 p_stream->pf_send = Send;
133 return VLC_SUCCESS;
136 /*****************************************************************************
137 * Close:
138 *****************************************************************************/
139 static void Close( vlc_object_t * p_this )
141 sout_stream_t *p_stream = (sout_stream_t*)p_this;
142 sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
144 if( p_sys->output )
145 fclose( p_sys->output );
147 free( p_sys->prefix );
148 free( p_sys );
151 static void *Add( sout_stream_t *p_stream, const es_format_t *p_fmt )
153 sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
154 sout_stream_id_sys_t *id;
156 id = malloc( sizeof( sout_stream_id_sys_t ) );
157 if( unlikely( !id ) )
158 return NULL;
160 id->id = p_fmt->i_id;
161 switch( p_fmt->i_cat)
163 case VIDEO_ES:
164 id->type = "Video";
165 break;
166 case AUDIO_ES:
167 id->type = "Audio";
168 break;
169 case SPU_ES:
170 id->type = "SPU";
171 break;
172 default:
173 id->type = "Data";
174 break;
176 id->next_id = NULL;
177 id->segment_number = 0;
178 id->previous_dts = VLC_TICK_INVALID;
179 id->track_duration = 0;
180 InitMD5( &id->hash );
182 msg_Dbg( p_stream, "%s: Adding track type:%s id:%d", p_sys->prefix, id->type, id->id);
184 if( p_stream->p_next )
185 id->next_id = sout_StreamIdAdd( p_stream->p_next, p_fmt );
187 return id;
190 static void Del( sout_stream_t *p_stream, void *_id )
192 sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
193 sout_stream_id_sys_t *id = (sout_stream_id_sys_t *)_id;
195 EndMD5( &id->hash );
196 char *outputhash = psz_md5_hash( &id->hash );
197 unsigned int num,den;
198 vlc_ureduce( &num, &den, id->track_duration, id->segment_number, 0 );
199 msg_Dbg( p_stream, "%s: Removing track type:%s id:%d", p_sys->prefix, id->type, id->id );
200 if( p_sys->output )
202 fprintf( p_sys->output,"#%s: final type:%s id:%d segments:%"PRIu64" total_duration:%"PRId64" avg_track:%d/%d md5:%16s\n",
203 p_sys->prefix, id->type, id->id, id->segment_number, id->track_duration, num, den, outputhash );
204 } else {
205 msg_Info( p_stream, "%s: final type:%s id:%d segments:%"PRIu64" total_duration:%"PRId64" avg_track:%d/%d md5:%16s",
206 p_sys->prefix, id->type, id->id, id->segment_number, id->track_duration, num, den, outputhash );
208 free( outputhash );
209 if( id->next_id ) sout_StreamIdDel( p_stream->p_next, id->next_id );
210 free( id );
213 static int Send( sout_stream_t *p_stream, void *_id, block_t *p_buffer )
215 sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
216 sout_stream_id_sys_t *id = (sout_stream_id_sys_t *)_id;
217 struct md5_s hash;
219 block_t *p_block = p_buffer;
220 while ( p_block != NULL )
222 InitMD5( &hash );
223 AddMD5( &hash, p_block->p_buffer, p_block->i_buffer );
224 AddMD5( &id->hash, p_block->p_buffer, p_block->i_buffer );
225 EndMD5( &hash );
226 char *outputhash = psz_md5_hash( &hash );
228 /* We could just set p_sys->output to stdout and remove user of msg_Dbg
229 * if we don't need ability to output info to gui modules (like qt messages window
231 vlc_tick_t dts_difference = VLC_TICK_INVALID;
232 if( likely( id->previous_dts != VLC_TICK_INVALID ) )
233 dts_difference = p_block->i_dts - id->previous_dts;
234 if( p_sys->output )
236 /* Write data in a form that it's easy to plot for example with gnuplot*/
237 fprintf( p_sys->output, "%s\t%d\t%s\t%"PRIu64"\t%"PRId64"\t%"PRId64"\t%16s\n",
238 p_sys->prefix, id->id, id->type, ++id->segment_number, dts_difference,
239 p_block->i_length, outputhash );
241 } else {
242 msg_Dbg( p_stream, "%s: track:%d type:%s segment_number:%"PRIu64" dts_difference:%"PRId64" length:%"PRId64" md5:%16s",
243 p_sys->prefix, id->id, id->type, ++id->segment_number, dts_difference,
244 p_block->i_length, outputhash );
246 id->track_duration += p_block->i_length ? p_block->i_length : dts_difference;
247 free( outputhash );
248 id->previous_dts = p_block->i_dts;
249 p_block = p_block->p_next;
252 if( p_stream->p_next )
253 return sout_StreamIdSend( p_stream->p_next, id->next_id, p_buffer );
254 else
255 block_Release( p_buffer );
256 return VLC_SUCCESS;