@@ -67,31 +67,31 @@ struct avi_port
6767 avi_writer_streams * streams ;
6868};
6969
70- static pj_status_t write_headers (avi_writer_streams * streams )
70+ static pj_status_t write_headers (pj_oshandle_t fd , avi_writer_streams * streams )
7171{
7272 unsigned i ;
7373 pj_ssize_t size ;
7474 pj_status_t status ;
7575
7676 /* Write AVI header. */
7777 size = sizeof (riff_hdr_t ) + sizeof (avih_hdr_t );
78- status = pj_file_write (streams -> fd , & streams -> avi_hdr , & size );
78+ status = pj_file_write (fd , & streams -> avi_hdr , & size );
7979 if (status != PJ_SUCCESS )
8080 return status ;
8181 streams -> total += size ;
8282
8383 /* Write stream headers. */
8484 for (i = 0 ; i < streams -> base .num_streams ; i ++ ) {
8585 size = sizeof (strl_hdr_t );
86- status = pj_file_write (streams -> fd , & streams -> avi_hdr .strl_hdr [i ],
86+ status = pj_file_write (fd , & streams -> avi_hdr .strl_hdr [i ],
8787 & size );
8888 if (status != PJ_SUCCESS )
8989 return status ;
9090 streams -> total += size ;
9191
9292 size = streams -> base .streams [i ]-> info .fmt .type == PJMEDIA_TYPE_AUDIO ?
9393 sizeof (strf_audio_hdr_t ): sizeof (strf_video_hdr_t );
94- status = pj_file_write (streams -> fd , & streams -> avi_hdr .strf_hdr [i ],
94+ status = pj_file_write (fd , & streams -> avi_hdr .strf_hdr [i ],
9595 & size );
9696 if (status != PJ_SUCCESS )
9797 return status ;
@@ -101,6 +101,55 @@ static pj_status_t write_headers(avi_writer_streams *streams)
101101 return PJ_SUCCESS ;
102102}
103103
104+ static void close_avi_file (avi_writer_streams * streams )
105+ {
106+ pj_off_t file_size ;
107+ unsigned i ;
108+ pj_status_t status ;
109+ pj_oshandle_t fd ;
110+
111+ /* First, reset file handle, best effort in handling race conditions */
112+ fd = streams -> fd ;
113+ streams -> fd = (pj_oshandle_t )(pj_ssize_t )- 1 ;
114+
115+ /* Already closed. */
116+ if (fd == (pj_oshandle_t )(pj_ssize_t )- 1 )
117+ return ;
118+
119+ /* Set AVI header's file length and total frames. */
120+ status = pj_file_getpos (fd , & file_size );
121+ if (status != PJ_SUCCESS )
122+ goto on_return ;
123+
124+ streams -> avi_hdr .riff_hdr .file_len = (pj_uint32_t )
125+ (file_size - 8 );
126+ pjmedia_avi_swap_data (& streams -> avi_hdr .riff_hdr .file_len ,
127+ sizeof (pj_uint32_t ), 32 );
128+ streams -> avi_hdr .avih_hdr .tot_frames = (pj_uint32_t )streams -> frame_cnt ;
129+ pjmedia_avi_swap_data (& streams -> avi_hdr .avih_hdr .tot_frames ,
130+ sizeof (pj_uint32_t ), 32 );
131+
132+ for (i = 0 ; i < streams -> base .num_streams ; i ++ ) {
133+ pjmedia_avi_swap_data (& streams -> avi_hdr .strl_hdr [i ].length ,
134+ sizeof (pj_uint32_t ), 32 );
135+ }
136+
137+ /* Rewrite headers. */
138+ status = pj_file_setpos (fd , 0 , PJ_SEEK_SET );
139+ if (status != PJ_SUCCESS )
140+ goto on_return ;
141+ status = write_headers (fd , streams );
142+ if (status != PJ_SUCCESS )
143+ goto on_return ;
144+
145+ on_return :
146+ pj_file_close (fd );
147+ if (status != PJ_SUCCESS ) {
148+ pj_perror (2 , THIS_FILE , status ,
149+ "Error updating length & frame count in AVI header" );
150+ }
151+ }
152+
104153static pj_status_t file_on_event (pjmedia_event * event ,
105154 void * user_data )
106155{
@@ -140,41 +189,10 @@ static pj_status_t avi_put_frame(pjmedia_port *this_port,
140189 if (fport -> streams -> total + frame -> size + sizeof (pjmedia_avi_subchunk ) >
141190 fport -> streams -> max_size )
142191 {
143- pj_off_t file_size ;
144- unsigned i ;
145-
146192 PJ_LOG (4 , (THIS_FILE , "AVI writer max size %zu reached" ,
147193 fport -> streams -> max_size ));
148194
149- /* Set AVI header's file length and total frames. */
150- status = pj_file_getpos (fport -> streams -> fd , & file_size );
151- if (status != PJ_SUCCESS )
152- goto on_return ;
153-
154- fport -> streams -> avi_hdr .riff_hdr .file_len = (pj_uint32_t )
155- (file_size - 8 );
156- pjmedia_avi_swap_data (& fport -> streams -> avi_hdr .riff_hdr .file_len ,
157- sizeof (pj_uint32_t ), 32 );
158- fport -> streams -> avi_hdr .avih_hdr .tot_frames = fport -> streams -> frame_cnt ;
159- pjmedia_avi_swap_data (& fport -> streams -> avi_hdr .avih_hdr .tot_frames ,
160- sizeof (pj_uint32_t ), 32 );
161-
162- for (i = 0 ; i < fport -> streams -> base .num_streams ; i ++ ) {
163- pjmedia_avi_swap_data (& fport -> streams -> avi_hdr .strl_hdr [i ].length ,
164- sizeof (pj_uint32_t ), 32 );
165- }
166-
167- /* Rewrite headers. */
168- status = pj_file_setpos (fport -> streams -> fd , 0 , PJ_SEEK_SET );
169- if (status != PJ_SUCCESS )
170- goto on_return ;
171- status = write_headers (fport -> streams );
172- if (status != PJ_SUCCESS )
173- goto on_return ;
174-
175- /* Close file. */
176- pj_file_close (fport -> streams -> fd );
177- fport -> streams -> fd = (pj_oshandle_t )(pj_ssize_t )- 1 ;
195+ close_avi_file (fport -> streams );
178196
179197 /* Call callback. */
180198 if (fport -> streams -> cb2 ) {
@@ -202,8 +220,10 @@ static pj_status_t avi_put_frame(pjmedia_port *this_port,
202220 /* Write subchunk header. */
203221 ch .id = 0 ;
204222 ((char * )& ch .id )[0 ] = '0' ;
205- ((char * )& ch .id )[1 ] = '0' + fport -> stream_id ;
206- ch .len = frame -> size ;
223+ ((char * )& ch .id )[1 ] = '0' + (char )fport -> stream_id ;
224+ ((char * )& ch .id )[2 ] = 'd' ;
225+ ((char * )& ch .id )[3 ] = 'b' ;
226+ ch .len = (pj_uint32_t )frame -> size ;
207227 size = sizeof (ch );
208228 pjmedia_avi_swap_data (& ch , sizeof (ch ), 32 );
209229
@@ -246,11 +266,7 @@ static void streams_on_destroy(void *arg)
246266 streams -> subscribed = PJ_FALSE ;
247267 }
248268
249- if (streams -> fd != (pj_oshandle_t ) (pj_ssize_t )- 1 ) {
250- pj_file_close (streams -> fd );
251- streams -> fd = (pj_oshandle_t )(pj_ssize_t )- 1 ;
252- }
253-
269+ close_avi_file (streams );
254270 pj_pool_safe_release (& streams -> base .pool );
255271}
256272
@@ -401,7 +417,7 @@ pjmedia_avi_writer_create_streams(pj_pool_t *pool_,
401417 avi_hdr .strl_hdr [i ].codec = format [i ].id ;
402418 avi_hdr .strl_hdr [i ].rate = afd -> clock_rate ;
403419 avi_hdr .strl_hdr [i ].scale = 1 ;
404- avi_hdr .strl_hdr [i ].quality = -1 ;
420+ avi_hdr .strl_hdr [i ].quality = ( pj_uint32_t ) - 1 ;
405421 avi_hdr .strl_hdr [i ].buf_size = 0 ;
406422 avi_hdr .strl_hdr [i ].sample_size = afd -> bits_per_sample / 8 ;
407423 avi_hdr .strl_hdr [i ].length = 0 ; /* will be filled later */
@@ -410,11 +426,12 @@ pjmedia_avi_writer_create_streams(pj_pool_t *pool_,
410426 strf_hdr -> strf = SET_TAG (PJMEDIA_AVI_STRF_TAG );
411427 strf_hdr -> strf_size = sizeof (strf_audio_hdr_t ) - 8 ;
412428 strf_hdr -> fmt_tag = 1 ; /* 1 for PCM */
413- strf_hdr -> nchannels = afd -> channel_count ;
429+ strf_hdr -> nchannels = ( pj_uint16_t ) afd -> channel_count ;
414430 strf_hdr -> sample_rate = afd -> clock_rate ;
415- strf_hdr -> block_align = afd -> channel_count * afd -> bits_per_sample / 8 ;
431+ strf_hdr -> block_align = (pj_uint16_t )(afd -> channel_count *
432+ afd -> bits_per_sample / 8 );
416433 strf_hdr -> bytes_per_sec = strf_hdr -> sample_rate * strf_hdr -> block_align ;
417- strf_hdr -> bits_per_sample = afd -> bits_per_sample ;
434+ strf_hdr -> bits_per_sample = ( pj_uint16_t ) afd -> bits_per_sample ;
418435
419436 /* Normalize header to AVI's little endian. */
420437 pjmedia_avi_swap_data (& avi_hdr .strl_hdr [i ], sizeof (strl_hdr_t ), 32 );
@@ -434,7 +451,7 @@ pjmedia_avi_writer_create_streams(pj_pool_t *pool_,
434451 goto on_error ;
435452
436453 /* Write headers. */
437- status = write_headers (streams );
454+ status = write_headers (streams -> fd , streams );
438455 if (status != PJ_SUCCESS )
439456 goto on_error ;
440457
0 commit comments