1 /*****************************************************************************
2 * muxers.c: h264 file i/o plugins
3 *****************************************************************************
4 * Copyright (C) 2003-2008 x264 project
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7 * Loren Merritt <lorenm@u.washington.edu>
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 02111, USA.
22 *****************************************************************************/
24 #include "common/common.h"
33 #include <sys/types.h>
41 #include <gpac/isomedia.h>
44 static int64_t gcd( int64_t a
, int64_t b
)
62 /* raw 420 yuv file operation */
63 int open_file_yuv( char *psz_filename
, hnd_t
*p_handle
, x264_param_t
*p_param
)
65 yuv_input_t
*h
= malloc(sizeof(yuv_input_t
));
66 h
->width
= p_param
->i_width
;
67 h
->height
= p_param
->i_height
;
70 if( !strcmp(psz_filename
, "-") )
73 h
->fh
= fopen(psz_filename
, "rb");
81 int get_frame_total_yuv( hnd_t handle
)
83 yuv_input_t
*h
= handle
;
84 int i_frame_total
= 0;
86 if( !fseek( h
->fh
, 0, SEEK_END
) )
88 uint64_t i_size
= ftell( h
->fh
);
89 fseek( h
->fh
, 0, SEEK_SET
);
90 i_frame_total
= (int)(i_size
/ ( h
->width
* h
->height
* 3 / 2 ));
96 int read_frame_yuv( x264_picture_t
*p_pic
, hnd_t handle
, int i_frame
)
98 yuv_input_t
*h
= handle
;
100 if( i_frame
!= h
->next_frame
)
101 if( fseek( h
->fh
, (uint64_t)i_frame
* h
->width
* h
->height
* 3 / 2, SEEK_SET
) )
104 if( fread( p_pic
->img
.plane
[0], 1, h
->width
* h
->height
, h
->fh
) <= 0
105 || fread( p_pic
->img
.plane
[1], 1, h
->width
* h
->height
/ 4, h
->fh
) <= 0
106 || fread( p_pic
->img
.plane
[2], 1, h
->width
* h
->height
/ 4, h
->fh
) <= 0 )
109 h
->next_frame
= i_frame
+1;
114 int close_file_yuv(hnd_t handle
)
116 yuv_input_t
*h
= handle
;
124 /* YUV4MPEG2 raw 420 yuv file operation */
129 int seq_header_len
, frame_header_len
;
133 #define Y4M_MAGIC "YUV4MPEG2"
134 #define MAX_YUV4_HEADER 80
135 #define Y4M_FRAME_MAGIC "FRAME"
136 #define MAX_FRAME_HEADER 80
138 int open_file_y4m( char *psz_filename
, hnd_t
*p_handle
, x264_param_t
*p_param
)
142 char header
[MAX_YUV4_HEADER
+10];
143 char *tokstart
, *tokend
, *header_end
;
144 y4m_input_t
*h
= malloc(sizeof(y4m_input_t
));
148 if( !strcmp(psz_filename
, "-") )
151 h
->fh
= fopen(psz_filename
, "rb");
155 h
->frame_header_len
= strlen(Y4M_FRAME_MAGIC
)+1;
158 for( i
=0; i
<MAX_YUV4_HEADER
; i
++ )
160 header
[i
] = fgetc(h
->fh
);
161 if( header
[i
] == '\n' )
163 /* Add a space after last option. Makes parsing "444" vs
164 "444alpha" easier. */
170 if( i
== MAX_YUV4_HEADER
|| strncmp(header
, Y4M_MAGIC
, strlen(Y4M_MAGIC
)) )
173 /* Scan properties */
174 header_end
= &header
[i
+1]; /* Include space */
175 h
->seq_header_len
= i
+1;
176 for( tokstart
= &header
[strlen(Y4M_MAGIC
)+1]; tokstart
< header_end
; tokstart
++ )
178 if(*tokstart
==0x20) continue;
181 case 'W': /* Width. Required. */
182 h
->width
= p_param
->i_width
= strtol(tokstart
, &tokend
, 10);
185 case 'H': /* Height. Required. */
186 h
->height
= p_param
->i_height
= strtol(tokstart
, &tokend
, 10);
189 case 'C': /* Color space */
190 if( strncmp("420", tokstart
, 3) )
192 fprintf(stderr
, "Colorspace unhandled\n");
195 tokstart
= strchr(tokstart
, 0x20);
197 case 'I': /* Interlace type */
200 case 'p': interlaced
= 0; break;
205 default: interlaced
= 1;
206 fprintf(stderr
, "Warning, this sequence might be interlaced\n");
209 case 'F': /* Frame rate - 0:0 if unknown */
210 if( sscanf(tokstart
, "%d:%d", &n
, &d
) == 2 && n
&& d
)
212 x264_reduce_fraction( &n
, &d
);
213 p_param
->i_fps_num
= n
;
214 p_param
->i_fps_den
= d
;
216 tokstart
= strchr(tokstart
, 0x20);
218 case 'A': /* Pixel aspect - 0:0 if unknown */
219 /* Don't override the aspect ratio if sar has been explicitly set on the commandline. */
220 if( sscanf(tokstart
, "%d:%d", &n
, &d
) == 2 && n
&& d
&& !p_param
->vui
.i_sar_width
&& !p_param
->vui
.i_sar_height
)
222 x264_reduce_fraction( &n
, &d
);
223 p_param
->vui
.i_sar_width
= n
;
224 p_param
->vui
.i_sar_height
= d
;
226 tokstart
= strchr(tokstart
, 0x20);
228 case 'X': /* Vendor extensions */
229 if( !strncmp("YSCSS=",tokstart
,6) )
231 /* Older nonstandard pixel format representation */
233 if( strncmp("420JPEG",tokstart
,7) &&
234 strncmp("420MPEG2",tokstart
,8) &&
235 strncmp("420PALDV",tokstart
,8) )
237 fprintf(stderr
, "Unsupported extended colorspace\n");
241 tokstart
= strchr(tokstart
, 0x20);
246 fprintf(stderr
, "yuv4mpeg: %ix%i@%i/%ifps, %i:%i\n",
247 h
->width
, h
->height
, p_param
->i_fps_num
, p_param
->i_fps_den
,
248 p_param
->vui
.i_sar_width
, p_param
->vui
.i_sar_height
);
250 *p_handle
= (hnd_t
)h
;
254 /* Most common case: frame_header = "FRAME" */
255 int get_frame_total_y4m( hnd_t handle
)
257 y4m_input_t
*h
= handle
;
258 int i_frame_total
= 0;
259 uint64_t init_pos
= ftell(h
->fh
);
261 if( !fseek( h
->fh
, 0, SEEK_END
) )
263 uint64_t i_size
= ftell( h
->fh
);
264 fseek( h
->fh
, init_pos
, SEEK_SET
);
265 i_frame_total
= (int)((i_size
- h
->seq_header_len
) /
266 (3*(h
->width
*h
->height
)/2+h
->frame_header_len
));
269 return i_frame_total
;
272 int read_frame_y4m( x264_picture_t
*p_pic
, hnd_t handle
, int i_frame
)
274 int slen
= strlen(Y4M_FRAME_MAGIC
);
277 y4m_input_t
*h
= handle
;
279 if( i_frame
!= h
->next_frame
)
281 if (fseek(h
->fh
, (uint64_t)i_frame
*(3*(h
->width
*h
->height
)/2+h
->frame_header_len
)
282 + h
->seq_header_len
, SEEK_SET
))
286 /* Read frame header - without terminating '\n' */
287 if (fread(header
, 1, slen
, h
->fh
) != slen
)
291 if (strncmp(header
, Y4M_FRAME_MAGIC
, slen
))
293 fprintf(stderr
, "Bad header magic (%08X <=> %s)\n",
294 *((uint32_t*)header
), header
);
298 /* Skip most of it */
299 while (i
<MAX_FRAME_HEADER
&& fgetc(h
->fh
) != '\n')
301 if (i
== MAX_FRAME_HEADER
)
303 fprintf(stderr
, "Bad frame header!\n");
306 h
->frame_header_len
= i
+slen
+1;
308 if( fread(p_pic
->img
.plane
[0], 1, h
->width
*h
->height
, h
->fh
) <= 0
309 || fread(p_pic
->img
.plane
[1], 1, h
->width
* h
->height
/ 4, h
->fh
) <= 0
310 || fread(p_pic
->img
.plane
[2], 1, h
->width
* h
->height
/ 4, h
->fh
) <= 0)
313 h
->next_frame
= i_frame
+1;
318 int close_file_y4m(hnd_t handle
)
320 y4m_input_t
*h
= handle
;
328 /* avs/avi input file support under cygwin */
336 int open_file_avis( char *psz_filename
, hnd_t
*p_handle
, x264_param_t
*p_param
)
338 avis_input_t
*h
= malloc(sizeof(avis_input_t
));
342 *p_handle
= (hnd_t
)h
;
345 if( AVIStreamOpenFromFile( &h
->p_avi
, psz_filename
, streamtypeVIDEO
, 0, OF_READ
, NULL
) )
351 if( AVIStreamInfo(h
->p_avi
, &info
, sizeof(AVISTREAMINFO
)) )
353 AVIStreamRelease(h
->p_avi
);
358 // check input format
359 if (info
.fccHandler
!= MAKEFOURCC('Y', 'V', '1', '2'))
361 fprintf( stderr
, "avis [error]: unsupported input format (%c%c%c%c)\n",
362 (char)(info
.fccHandler
& 0xff), (char)((info
.fccHandler
>> 8) & 0xff),
363 (char)((info
.fccHandler
>> 16) & 0xff), (char)((info
.fccHandler
>> 24)) );
365 AVIStreamRelease(h
->p_avi
);
372 p_param
->i_width
= info
.rcFrame
.right
- info
.rcFrame
.left
;
374 p_param
->i_height
= info
.rcFrame
.bottom
- info
.rcFrame
.top
;
375 i
= gcd(info
.dwRate
, info
.dwScale
);
376 p_param
->i_fps_den
= info
.dwScale
/ i
;
377 p_param
->i_fps_num
= info
.dwRate
/ i
;
379 fprintf( stderr
, "avis [info]: %dx%d @ %.2f fps (%d frames)\n",
380 p_param
->i_width
, p_param
->i_height
,
381 (double)p_param
->i_fps_num
/ (double)p_param
->i_fps_den
,
382 (int)info
.dwLength
);
387 int get_frame_total_avis( hnd_t handle
)
389 avis_input_t
*h
= handle
;
392 if( AVIStreamInfo(h
->p_avi
, &info
, sizeof(AVISTREAMINFO
)) )
395 return info
.dwLength
;
398 int read_frame_avis( x264_picture_t
*p_pic
, hnd_t handle
, int i_frame
)
400 avis_input_t
*h
= handle
;
402 p_pic
->img
.i_csp
= X264_CSP_YV12
;
404 if( AVIStreamRead(h
->p_avi
, i_frame
, 1, p_pic
->img
.plane
[0], h
->width
* h
->height
* 3 / 2, NULL
, NULL
) )
410 int close_file_avis( hnd_t handle
)
412 avis_input_t
*h
= handle
;
413 AVIStreamRelease(h
->p_avi
);
423 int (*p_read_frame
)( x264_picture_t
*p_pic
, hnd_t handle
, int i_frame
);
424 int (*p_close_infile
)( hnd_t handle
);
431 struct thread_input_arg_t
*next_args
;
434 typedef struct thread_input_arg_t
{
439 } thread_input_arg_t
;
441 int open_file_thread( char *psz_filename
, hnd_t
*p_handle
, x264_param_t
*p_param
)
443 thread_input_t
*h
= malloc(sizeof(thread_input_t
));
444 x264_picture_alloc( &h
->pic
, X264_CSP_I420
, p_param
->i_width
, p_param
->i_height
);
445 h
->p_read_frame
= p_read_frame
;
446 h
->p_close_infile
= p_close_infile
;
447 h
->p_handle
= *p_handle
;
450 h
->next_args
= malloc(sizeof(thread_input_arg_t
));
452 h
->next_args
->status
= 0;
453 h
->frame_total
= p_get_frame_total( h
->p_handle
);
455 *p_handle
= (hnd_t
)h
;
459 int get_frame_total_thread( hnd_t handle
)
461 thread_input_t
*h
= handle
;
462 return h
->frame_total
;
465 static void read_frame_thread_int( thread_input_arg_t
*i
)
467 i
->status
= i
->h
->p_read_frame( i
->pic
, i
->h
->p_handle
, i
->i_frame
);
470 int read_frame_thread( x264_picture_t
*p_pic
, hnd_t handle
, int i_frame
)
472 thread_input_t
*h
= handle
;
476 if( h
->next_frame
>= 0 )
478 x264_pthread_join( h
->tid
, &stuff
);
479 ret
|= h
->next_args
->status
;
483 if( h
->next_frame
== i_frame
)
485 XCHG( x264_picture_t
, *p_pic
, h
->pic
);
489 ret
|= h
->p_read_frame( p_pic
, h
->p_handle
, i_frame
);
492 if( !h
->frame_total
|| i_frame
+1 < h
->frame_total
)
495 h
->next_args
->i_frame
= i_frame
+1;
496 h
->next_args
->pic
= &h
->pic
;
497 x264_pthread_create( &h
->tid
, NULL
, (void*)read_frame_thread_int
, h
->next_args
);
506 int close_file_thread( hnd_t handle
)
508 thread_input_t
*h
= handle
;
509 h
->p_close_infile( h
->p_handle
);
510 x264_picture_clean( &h
->pic
);
512 x264_pthread_join( h
->tid
, NULL
);
513 free( h
->next_args
);
520 int open_file_bsf( char *psz_filename
, hnd_t
*p_handle
)
522 if ((*p_handle
= fopen(psz_filename
, "w+b")) == NULL
)
528 int set_param_bsf( hnd_t handle
, x264_param_t
*p_param
)
533 int write_nalu_bsf( hnd_t handle
, uint8_t *p_nalu
, int i_size
)
535 if (fwrite(p_nalu
, i_size
, 1, (FILE *)handle
) > 0)
540 int set_eop_bsf( hnd_t handle
, x264_picture_t
*p_picture
)
545 int close_file_bsf( hnd_t handle
)
547 if ((handle
== NULL
) || (handle
== stdout
))
550 return fclose((FILE *)handle
);
553 /* -- mp4 muxing support ------------------------------------------------- */
559 GF_AVCConfig
*p_config
;
560 GF_ISOSample
*p_sample
;
572 static void recompute_bitrate_mp4(GF_ISOFile
*p_file
, int i_track
)
574 u32 i
, count
, di
, timescale
, time_wnd
, rate
;
579 esd
= gf_isom_get_esd(p_file
, i_track
, 1);
582 esd
->decoderConfig
->avgBitrate
= 0;
583 esd
->decoderConfig
->maxBitrate
= 0;
586 timescale
= gf_isom_get_media_timescale(p_file
, i_track
);
587 count
= gf_isom_get_sample_count(p_file
, i_track
);
588 for (i
=0; i
<count
; i
++) {
589 GF_ISOSample
*samp
= gf_isom_get_sample_info(p_file
, i_track
, i
+1, &di
, &offset
);
591 if (samp
->dataLength
>esd
->decoderConfig
->bufferSizeDB
) esd
->decoderConfig
->bufferSizeDB
= samp
->dataLength
;
593 if (esd
->decoderConfig
->bufferSizeDB
< samp
->dataLength
) esd
->decoderConfig
->bufferSizeDB
= samp
->dataLength
;
594 esd
->decoderConfig
->avgBitrate
+= samp
->dataLength
;
595 rate
+= samp
->dataLength
;
596 if (samp
->DTS
> time_wnd
+ timescale
) {
597 if (rate
> esd
->decoderConfig
->maxBitrate
) esd
->decoderConfig
->maxBitrate
= rate
;
598 time_wnd
= samp
->DTS
;
602 gf_isom_sample_del(&samp
);
605 br
= (Double
) (s64
) gf_isom_get_media_duration(p_file
, i_track
);
607 esd
->decoderConfig
->avgBitrate
= (u32
) (esd
->decoderConfig
->avgBitrate
/ br
);
609 esd
->decoderConfig
->avgBitrate
*= 8;
610 esd
->decoderConfig
->maxBitrate
*= 8;
612 gf_isom_change_mpeg4_description(p_file
, i_track
, 1, esd
);
613 gf_odf_desc_del((GF_Descriptor
*) esd
);
617 int close_file_mp4( hnd_t handle
)
619 mp4_t
*p_mp4
= (mp4_t
*)handle
;
625 gf_odf_avc_cfg_del(p_mp4
->p_config
);
629 if (p_mp4
->p_sample
->data
)
630 free(p_mp4
->p_sample
->data
);
632 gf_isom_sample_del(&p_mp4
->p_sample
);
637 recompute_bitrate_mp4(p_mp4
->p_file
, p_mp4
->i_track
);
638 gf_isom_set_pl_indication(p_mp4
->p_file
, GF_ISOM_PL_VISUAL
, 0x15);
639 gf_isom_set_storage_mode(p_mp4
->p_file
, GF_ISOM_STORE_FLAT
);
640 gf_isom_close(p_mp4
->p_file
);
648 int open_file_mp4( char *psz_filename
, hnd_t
*p_handle
)
654 if ((p_mp4
= (mp4_t
*)malloc(sizeof(mp4_t
))) == NULL
)
657 memset(p_mp4
, 0, sizeof(mp4_t
));
658 p_mp4
->p_file
= gf_isom_open(psz_filename
, GF_ISOM_OPEN_WRITE
, NULL
);
660 if ((p_mp4
->p_sample
= gf_isom_sample_new()) == NULL
)
662 close_file_mp4( p_mp4
);
666 gf_isom_set_brand_info(p_mp4
->p_file
, GF_ISOM_BRAND_AVC1
, 0);
674 int set_param_mp4( hnd_t handle
, x264_param_t
*p_param
)
676 mp4_t
*p_mp4
= (mp4_t
*)handle
;
678 p_mp4
->i_track
= gf_isom_new_track(p_mp4
->p_file
, 0, GF_ISOM_MEDIA_VISUAL
,
681 p_mp4
->p_config
= gf_odf_avc_cfg_new();
682 gf_isom_avc_config_new(p_mp4
->p_file
, p_mp4
->i_track
, p_mp4
->p_config
,
683 NULL
, NULL
, &p_mp4
->i_descidx
);
685 gf_isom_set_track_enabled(p_mp4
->p_file
, p_mp4
->i_track
, 1);
687 gf_isom_set_visual_info(p_mp4
->p_file
, p_mp4
->i_track
, p_mp4
->i_descidx
,
688 p_param
->i_width
, p_param
->i_height
);
690 if( p_param
->vui
.i_sar_width
&& p_param
->vui
.i_sar_height
)
692 uint64_t dw
= p_param
->i_width
<< 16;
693 uint64_t dh
= p_param
->i_height
<< 16;
694 double sar
= (double)p_param
->vui
.i_sar_width
/ p_param
->vui
.i_sar_height
;
699 gf_isom_set_track_layout_info( p_mp4
->p_file
, p_mp4
->i_track
, dw
, dh
, 0, 0, 0 );
702 p_mp4
->p_sample
->data
= (char *)malloc(p_param
->i_width
* p_param
->i_height
* 3 / 2);
703 if (p_mp4
->p_sample
->data
== NULL
)
706 p_mp4
->i_time_res
= p_param
->i_fps_num
;
707 p_mp4
->i_time_inc
= p_param
->i_fps_den
;
708 p_mp4
->i_init_delay
= p_param
->i_bframe
? (p_param
->b_bframe_pyramid
? 2 : 1) : 0;
709 p_mp4
->i_init_delay
*= p_mp4
->i_time_inc
;
710 fprintf(stderr
, "mp4 [info]: initial delay %d (scale %d)\n",
711 p_mp4
->i_init_delay
, p_mp4
->i_time_res
);
717 int write_nalu_mp4( hnd_t handle
, uint8_t *p_nalu
, int i_size
)
719 mp4_t
*p_mp4
= (mp4_t
*)handle
;
720 GF_AVCConfigSlot
*p_slot
;
721 uint8_t type
= p_nalu
[4] & 0x1f;
730 p_mp4
->p_config
->configurationVersion
= 1;
731 p_mp4
->p_config
->AVCProfileIndication
= p_nalu
[5];
732 p_mp4
->p_config
->profile_compatibility
= p_nalu
[6];
733 p_mp4
->p_config
->AVCLevelIndication
= p_nalu
[7];
734 p_slot
= (GF_AVCConfigSlot
*)malloc(sizeof(GF_AVCConfigSlot
));
735 p_slot
->size
= i_size
- 4;
736 p_slot
->data
= (char *)malloc(p_slot
->size
);
737 memcpy(p_slot
->data
, p_nalu
+ 4, i_size
- 4);
738 gf_list_add(p_mp4
->p_config
->sequenceParameterSets
, p_slot
);
748 p_slot
= (GF_AVCConfigSlot
*)malloc(sizeof(GF_AVCConfigSlot
));
749 p_slot
->size
= i_size
- 4;
750 p_slot
->data
= (char *)malloc(p_slot
->size
);
751 memcpy(p_slot
->data
, p_nalu
+ 4, i_size
- 4);
752 gf_list_add(p_mp4
->p_config
->pictureParameterSets
, p_slot
);
756 gf_isom_avc_config_update(p_mp4
->p_file
, p_mp4
->i_track
, 1, p_mp4
->p_config
);
765 memcpy(p_mp4
->p_sample
->data
+ p_mp4
->p_sample
->dataLength
, p_nalu
, i_size
);
766 p_mp4
->p_sample
->data
[p_mp4
->p_sample
->dataLength
+ 0] = (psize
>> 24) & 0xff;
767 p_mp4
->p_sample
->data
[p_mp4
->p_sample
->dataLength
+ 1] = (psize
>> 16) & 0xff;
768 p_mp4
->p_sample
->data
[p_mp4
->p_sample
->dataLength
+ 2] = (psize
>> 8) & 0xff;
769 p_mp4
->p_sample
->data
[p_mp4
->p_sample
->dataLength
+ 3] = (psize
>> 0) & 0xff;
770 p_mp4
->p_sample
->dataLength
+= i_size
;
777 int set_eop_mp4( hnd_t handle
, x264_picture_t
*p_picture
)
779 mp4_t
*p_mp4
= (mp4_t
*)handle
;
780 uint64_t dts
= (uint64_t)p_mp4
->i_numframe
* p_mp4
->i_time_inc
;
781 uint64_t pts
= (uint64_t)p_picture
->i_pts
;
782 int32_t offset
= p_mp4
->i_init_delay
+ pts
- dts
;
784 p_mp4
->p_sample
->IsRAP
= p_picture
->i_type
== X264_TYPE_IDR
? 1 : 0;
785 p_mp4
->p_sample
->DTS
= dts
;
786 p_mp4
->p_sample
->CTS_Offset
= offset
;
787 gf_isom_add_sample(p_mp4
->p_file
, p_mp4
->i_track
, p_mp4
->i_descidx
, p_mp4
->p_sample
);
789 p_mp4
->p_sample
->dataLength
= 0;
798 /* -- mkv muxing support ------------------------------------------------- */
804 int sps_len
, pps_len
;
806 int width
, height
, d_width
, d_height
;
808 int64_t frame_duration
;
811 int b_header_written
;
812 char b_writing_frame
;
815 static int write_header_mkv( mkv_t
*p_mkv
)
821 if( p_mkv
->sps
== NULL
|| p_mkv
->pps
== NULL
||
822 p_mkv
->width
== 0 || p_mkv
->height
== 0 ||
823 p_mkv
->d_width
== 0 || p_mkv
->d_height
== 0)
826 avcC_len
= 5 + 1 + 2 + p_mkv
->sps_len
+ 1 + 2 + p_mkv
->pps_len
;
827 avcC
= malloc(avcC_len
);
832 avcC
[1] = p_mkv
->sps
[1];
833 avcC
[2] = p_mkv
->sps
[2];
834 avcC
[3] = p_mkv
->sps
[3];
835 avcC
[4] = 0xff; // nalu size length is four bytes
836 avcC
[5] = 0xe1; // one sps
838 avcC
[6] = p_mkv
->sps_len
>> 8;
839 avcC
[7] = p_mkv
->sps_len
;
841 memcpy(avcC
+8, p_mkv
->sps
, p_mkv
->sps_len
);
843 avcC
[8+p_mkv
->sps_len
] = 1; // one pps
844 avcC
[9+p_mkv
->sps_len
] = p_mkv
->pps_len
>> 8;
845 avcC
[10+p_mkv
->sps_len
] = p_mkv
->pps_len
;
847 memcpy( avcC
+11+p_mkv
->sps_len
, p_mkv
->pps
, p_mkv
->pps_len
);
849 ret
= mk_writeHeader( p_mkv
->w
, "x264", "V_MPEG4/ISO/AVC",
850 avcC
, avcC_len
, p_mkv
->frame_duration
, 50000,
851 p_mkv
->width
, p_mkv
->height
,
852 p_mkv
->d_width
, p_mkv
->d_height
);
856 p_mkv
->b_header_written
= 1;
861 int open_file_mkv( char *psz_filename
, hnd_t
*p_handle
)
867 p_mkv
= malloc(sizeof(*p_mkv
));
871 memset(p_mkv
, 0, sizeof(*p_mkv
));
873 p_mkv
->w
= mk_createWriter(psz_filename
);
874 if (p_mkv
->w
== NULL
)
885 int set_param_mkv( hnd_t handle
, x264_param_t
*p_param
)
887 mkv_t
*p_mkv
= handle
;
890 if( p_param
->i_fps_num
> 0 )
892 p_mkv
->frame_duration
= (int64_t)p_param
->i_fps_den
*
893 (int64_t)1000000000 / p_param
->i_fps_num
;
894 p_mkv
->fps_num
= p_param
->i_fps_num
;
898 p_mkv
->frame_duration
= 0;
902 p_mkv
->width
= p_param
->i_width
;
903 p_mkv
->height
= p_param
->i_height
;
905 if( p_param
->vui
.i_sar_width
&& p_param
->vui
.i_sar_height
)
907 dw
= (int64_t)p_param
->i_width
* p_param
->vui
.i_sar_width
;
908 dh
= (int64_t)p_param
->i_height
* p_param
->vui
.i_sar_height
;
912 dw
= p_param
->i_width
;
913 dh
= p_param
->i_height
;
916 if( dw
> 0 && dh
> 0 )
918 int64_t x
= gcd( dw
, dh
);
923 p_mkv
->d_width
= (int)dw
;
924 p_mkv
->d_height
= (int)dh
;
929 int write_nalu_mkv( hnd_t handle
, uint8_t *p_nalu
, int i_size
)
931 mkv_t
*p_mkv
= handle
;
932 uint8_t type
= p_nalu
[4] & 0x1f;
942 p_mkv
->sps
= malloc(i_size
- 4);
943 if (p_mkv
->sps
== NULL
)
945 p_mkv
->sps_len
= i_size
- 4;
946 memcpy(p_mkv
->sps
, p_nalu
+ 4, i_size
- 4);
954 p_mkv
->pps
= malloc(i_size
- 4);
955 if (p_mkv
->pps
== NULL
)
957 p_mkv
->pps_len
= i_size
- 4;
958 memcpy(p_mkv
->pps
, p_nalu
+ 4, i_size
- 4);
966 if( !p_mkv
->b_writing_frame
)
968 if( mk_startFrame(p_mkv
->w
) < 0 )
970 p_mkv
->b_writing_frame
= 1;
973 dsize
[0] = psize
>> 24;
974 dsize
[1] = psize
>> 16;
975 dsize
[2] = psize
>> 8;
977 if( mk_addFrameData(p_mkv
->w
, dsize
, 4) < 0 ||
978 mk_addFrameData(p_mkv
->w
, p_nalu
+ 4, i_size
- 4) < 0 )
986 if( !p_mkv
->b_header_written
&& p_mkv
->pps
&& p_mkv
->sps
&&
987 write_header_mkv(p_mkv
) < 0 )
993 int set_eop_mkv( hnd_t handle
, x264_picture_t
*p_picture
)
995 mkv_t
*p_mkv
= handle
;
996 int64_t i_stamp
= (int64_t)(p_picture
->i_pts
* 1e9
/ p_mkv
->fps_num
);
998 p_mkv
->b_writing_frame
= 0;
1000 return mk_setFrameFlags( p_mkv
->w
, i_stamp
,
1001 p_picture
->i_type
== X264_TYPE_IDR
);
1004 int close_file_mkv( hnd_t handle
)
1006 mkv_t
*p_mkv
= handle
;
1014 ret
= mk_close(p_mkv
->w
);