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 )
63 /* raw 420 yuv file operation */
64 int open_file_yuv( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
66 yuv_input_t *h = malloc( sizeof(yuv_input_t) );
69 h->width = p_param->i_width;
70 h->height = p_param->i_height;
73 if( !strcmp( psz_filename, "-" ) )
76 h->fh = fopen( psz_filename, "rb" );
84 int get_frame_total_yuv( hnd_t handle )
86 yuv_input_t *h = handle;
87 int i_frame_total = 0;
89 if( !fseek( h->fh, 0, SEEK_END ) )
91 uint64_t i_size = ftell( h->fh );
92 fseek( h->fh, 0, SEEK_SET );
93 i_frame_total = (int)(i_size / ( h->width * h->height * 3 / 2 ));
99 int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame )
101 yuv_input_t *h = handle;
103 if( i_frame != h->next_frame )
104 if( fseek( h->fh, (uint64_t)i_frame * h->width * h->height * 3 / 2, SEEK_SET ) )
107 if( fread( p_pic->img.plane[0], 1, h->width * h->height, h->fh ) <= 0
108 || fread( p_pic->img.plane[1], 1, h->width * h->height / 4, h->fh ) <= 0
109 || fread( p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh ) <= 0 )
112 h->next_frame = i_frame+1;
117 int close_file_yuv(hnd_t handle)
119 yuv_input_t *h = handle;
127 /* YUV4MPEG2 raw 420 yuv file operation */
133 int seq_header_len, frame_header_len;
137 #define Y4M_MAGIC "YUV4MPEG2"
138 #define MAX_YUV4_HEADER 80
139 #define Y4M_FRAME_MAGIC "FRAME"
140 #define MAX_FRAME_HEADER 80
142 int open_file_y4m( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
145 char header[MAX_YUV4_HEADER+10];
146 char *tokstart, *tokend, *header_end;
147 y4m_input_t *h = malloc( sizeof(y4m_input_t) );
153 if( !strcmp( psz_filename, "-" ) )
156 h->fh = fopen(psz_filename, "rb");
160 h->frame_header_len = strlen(Y4M_FRAME_MAGIC)+1;
163 for( i = 0; i < MAX_YUV4_HEADER; i++ )
165 header[i] = fgetc(h->fh);
166 if( header[i] == '\n' )
168 /* Add a space after last option. Makes parsing "444" vs
169 "444alpha" easier. */
175 if( i == MAX_YUV4_HEADER || strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC)) )
178 /* Scan properties */
179 header_end = &header[i+1]; /* Include space */
180 h->seq_header_len = i+1;
181 for( tokstart = &header[strlen(Y4M_MAGIC)+1]; tokstart < header_end; tokstart++ )
183 if( *tokstart == 0x20 )
187 case 'W': /* Width. Required. */
188 h->width = p_param->i_width = strtol( tokstart, &tokend, 10 );
191 case 'H': /* Height. Required. */
192 h->height = p_param->i_height = strtol( tokstart, &tokend, 10 );
195 case 'C': /* Color space */
196 if( strncmp( "420", tokstart, 3 ) )
198 fprintf( stderr, "Colorspace unhandled\n" );
201 tokstart = strchr( tokstart, 0x20 );
203 case 'I': /* Interlace type */
204 switch( *tokstart++ )
212 fprintf( stderr, "Warning, this sequence might be interlaced\n" );
215 case 'F': /* Frame rate - 0:0 if unknown */
216 if( sscanf( tokstart, "%d:%d", &n, &d ) == 2 && n && d )
218 x264_reduce_fraction( &n, &d );
219 p_param->i_fps_num = n;
220 p_param->i_fps_den = d;
222 tokstart = strchr( tokstart, 0x20 );
224 case 'A': /* Pixel aspect - 0:0 if unknown */
225 /* Don't override the aspect ratio if sar has been explicitly set on the commandline. */
226 if( sscanf( tokstart, "%d:%d", &n, &d ) == 2 && n && d && !p_param->vui.i_sar_width && !p_param->vui.i_sar_height )
228 x264_reduce_fraction( &n, &d );
229 p_param->vui.i_sar_width = n;
230 p_param->vui.i_sar_height = d;
232 tokstart = strchr( tokstart, 0x20 );
234 case 'X': /* Vendor extensions */
235 if( !strncmp( "YSCSS=", tokstart, 6 ) )
237 /* Older nonstandard pixel format representation */
239 if( strncmp( "420JPEG",tokstart, 7 ) &&
240 strncmp( "420MPEG2",tokstart, 8 ) &&
241 strncmp( "420PALDV",tokstart, 8 ) )
243 fprintf( stderr, "Unsupported extended colorspace\n" );
247 tokstart = strchr(tokstart, 0x20);
252 fprintf( stderr, "yuv4mpeg: %ix%i@%i/%ifps, %i:%i\n",
253 h->width, h->height, p_param->i_fps_num, p_param->i_fps_den,
254 p_param->vui.i_sar_width, p_param->vui.i_sar_height );
256 *p_handle = (hnd_t)h;
260 /* Most common case: frame_header = "FRAME" */
261 int get_frame_total_y4m( hnd_t handle )
263 y4m_input_t *h = handle;
264 int i_frame_total = 0;
265 uint64_t init_pos = ftell(h->fh);
267 if( !fseek( h->fh, 0, SEEK_END ) )
269 uint64_t i_size = ftell( h->fh );
270 fseek( h->fh, init_pos, SEEK_SET );
271 i_frame_total = (int)((i_size - h->seq_header_len) /
272 (3*(h->width*h->height)/2+h->frame_header_len));
275 return i_frame_total;
278 int read_frame_y4m( x264_picture_t *p_pic, hnd_t handle, int i_frame )
280 int slen = strlen(Y4M_FRAME_MAGIC);
283 y4m_input_t *h = handle;
285 if( i_frame != h->next_frame )
287 if( fseek( h->fh, (uint64_t)i_frame*(3*(h->width*h->height)/2+h->frame_header_len)
288 + h->seq_header_len, SEEK_SET ) )
292 /* Read frame header - without terminating '\n' */
293 if( fread( header, 1, slen, h->fh ) != slen )
297 if( strncmp( header, Y4M_FRAME_MAGIC, slen ) )
299 fprintf( stderr, "Bad header magic (%"PRIx32" <=> %s)\n",
300 *((uint32_t*)header), header );
304 /* Skip most of it */
305 while( i<MAX_FRAME_HEADER && fgetc(h->fh) != '\n' )
307 if( i == MAX_FRAME_HEADER )
309 fprintf( stderr, "Bad frame header!\n" );
312 h->frame_header_len = i+slen+1;
314 if( fread( p_pic->img.plane[0], 1, h->width*h->height, h->fh ) <= 0
315 || fread( p_pic->img.plane[1], 1, h->width * h->height / 4, h->fh ) <= 0
316 || fread( p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh ) <= 0)
319 h->next_frame = i_frame+1;
324 int close_file_y4m(hnd_t handle)
326 y4m_input_t *h = handle;
334 /* avs/avi input file support under cygwin */
343 int open_file_avis( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
345 avis_input_t *h = malloc( sizeof(avis_input_t) );
351 *p_handle = (hnd_t)h;
354 if( AVIStreamOpenFromFile( &h->p_avi, psz_filename, streamtypeVIDEO, 0, OF_READ, NULL ) )
360 if( AVIStreamInfo( h->p_avi, &info, sizeof(AVISTREAMINFO) ) )
362 AVIStreamRelease(h->p_avi);
367 // check input format
368 if( info.fccHandler != MAKEFOURCC('Y', 'V', '1', '2') )
370 fprintf( stderr, "avis [error]: unsupported input format (%c%c%c%c)\n",
371 (char)(info.fccHandler & 0xff), (char)((info.fccHandler >> 8) & 0xff),
372 (char)((info.fccHandler >> 16) & 0xff), (char)((info.fccHandler >> 24)) );
374 AVIStreamRelease( h->p_avi );
381 p_param->i_width = info.rcFrame.right - info.rcFrame.left;
383 p_param->i_height = info.rcFrame.bottom - info.rcFrame.top;
384 i = gcd(info.dwRate, info.dwScale);
385 p_param->i_fps_den = info.dwScale / i;
386 p_param->i_fps_num = info.dwRate / i;
388 fprintf( stderr, "avis [info]: %dx%d @ %.2f fps (%d frames)\n",
389 p_param->i_width, p_param->i_height,
390 (double)p_param->i_fps_num / (double)p_param->i_fps_den,
391 (int)info.dwLength );
396 int get_frame_total_avis( hnd_t handle )
398 avis_input_t *h = handle;
401 if( AVIStreamInfo( h->p_avi, &info, sizeof(AVISTREAMINFO) ) )
404 return info.dwLength;
407 int read_frame_avis( x264_picture_t *p_pic, hnd_t handle, int i_frame )
409 avis_input_t *h = handle;
411 p_pic->img.i_csp = X264_CSP_YV12;
413 if( AVIStreamRead( h->p_avi, i_frame, 1, p_pic->img.plane[0], h->width * h->height * 3 / 2, NULL, NULL ) )
419 int close_file_avis( hnd_t handle )
421 avis_input_t *h = handle;
422 AVIStreamRelease( h->p_avi );
433 int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame );
434 int (*p_close_infile)( hnd_t handle );
441 struct thread_input_arg_t *next_args;
444 typedef struct thread_input_arg_t
450 } thread_input_arg_t;
452 int open_file_thread( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
454 thread_input_t *h = malloc( sizeof(thread_input_t) );
455 if( !h || x264_picture_alloc( &h->pic, X264_CSP_I420, p_param->i_width, p_param->i_height ) < 0 )
457 fprintf( stderr, "x264 [error]: malloc failed\n" );
460 h->p_read_frame = p_read_frame;
461 h->p_close_infile = p_close_infile;
462 h->p_handle = *p_handle;
465 h->next_args = malloc(sizeof(thread_input_arg_t));
469 h->next_args->status = 0;
470 h->frame_total = p_get_frame_total( h->p_handle );
472 *p_handle = (hnd_t)h;
476 int get_frame_total_thread( hnd_t handle )
478 thread_input_t *h = handle;
479 return h->frame_total;
482 static void read_frame_thread_int( thread_input_arg_t *i )
484 i->status = i->h->p_read_frame( i->pic, i->h->p_handle, i->i_frame );
487 int read_frame_thread( x264_picture_t *p_pic, hnd_t handle, int i_frame )
489 thread_input_t *h = handle;
492 if( h->next_frame >= 0 )
494 x264_pthread_join( h->tid, NULL );
495 ret |= h->next_args->status;
499 if( h->next_frame == i_frame )
501 XCHG( x264_picture_t, *p_pic, h->pic );
505 ret |= h->p_read_frame( p_pic, h->p_handle, i_frame );
508 if( !h->frame_total || i_frame+1 < h->frame_total )
511 h->next_args->i_frame = i_frame+1;
512 h->next_args->pic = &h->pic;
513 if( x264_pthread_create( &h->tid, NULL, (void*)read_frame_thread_int, h->next_args ) )
523 int close_file_thread( hnd_t handle )
525 thread_input_t *h = handle;
527 x264_pthread_join( h->tid, NULL );
528 h->p_close_infile( h->p_handle );
529 x264_picture_clean( &h->pic );
530 free( h->next_args );
537 int open_file_bsf( char *psz_filename, hnd_t *p_handle )
539 if( !(*p_handle = fopen(psz_filename, "w+b")) )
545 int set_param_bsf( hnd_t handle, x264_param_t *p_param )
550 int write_nalu_bsf( hnd_t handle, uint8_t *p_nalu, int i_size )
552 if( fwrite( p_nalu, i_size, 1, (FILE*)handle ) > 0 )
557 int set_eop_bsf( hnd_t handle, x264_picture_t *p_picture )
562 int close_file_bsf( hnd_t handle )
564 if( !handle || handle == stdout )
567 return fclose( (FILE*)handle );
570 /* -- mp4 muxing support ------------------------------------------------- */
576 GF_AVCConfig *p_config;
577 GF_ISOSample *p_sample;
589 static void recompute_bitrate_mp4(GF_ISOFile *p_file, int i_track)
591 u32 i, count, di, timescale, time_wnd, rate;
596 esd = gf_isom_get_esd( p_file, i_track, 1 );
600 esd->decoderConfig->avgBitrate = 0;
601 esd->decoderConfig->maxBitrate = 0;
604 timescale = gf_isom_get_media_timescale( p_file, i_track );
605 count = gf_isom_get_sample_count( p_file, i_track );
606 for( i = 0; i < count; i++ )
608 GF_ISOSample *samp = gf_isom_get_sample_info( p_file, i_track, i+1, &di, &offset );
610 if( samp->dataLength>esd->decoderConfig->bufferSizeDB )
611 esd->decoderConfig->bufferSizeDB = samp->dataLength;
613 if( esd->decoderConfig->bufferSizeDB < samp->dataLength )
614 esd->decoderConfig->bufferSizeDB = samp->dataLength;
616 esd->decoderConfig->avgBitrate += samp->dataLength;
617 rate += samp->dataLength;
618 if( samp->DTS > time_wnd + timescale )
620 if( rate > esd->decoderConfig->maxBitrate )
621 esd->decoderConfig->maxBitrate = rate;
622 time_wnd = samp->DTS;
626 gf_isom_sample_del( &samp );
629 br = (Double)(s64)gf_isom_get_media_duration( p_file, i_track );
631 esd->decoderConfig->avgBitrate = (u32)(esd->decoderConfig->avgBitrate / br);
633 esd->decoderConfig->avgBitrate *= 8;
634 esd->decoderConfig->maxBitrate *= 8;
636 gf_isom_change_mpeg4_description( p_file, i_track, 1, esd );
637 gf_odf_desc_del( (GF_Descriptor*)esd );
641 int close_file_mp4( hnd_t handle )
643 mp4_t *p_mp4 = (mp4_t*)handle;
648 if( p_mp4->p_config )
649 gf_odf_avc_cfg_del( p_mp4->p_config );
651 if( p_mp4->p_sample )
653 if( p_mp4->p_sample->data )
654 free( p_mp4->p_sample->data );
656 gf_isom_sample_del( &p_mp4->p_sample );
661 recompute_bitrate_mp4( p_mp4->p_file, p_mp4->i_track );
662 gf_isom_set_pl_indication( p_mp4->p_file, GF_ISOM_PL_VISUAL, 0x15 );
663 gf_isom_set_storage_mode( p_mp4->p_file, GF_ISOM_STORE_FLAT );
664 gf_isom_close( p_mp4->p_file );
672 int open_file_mp4( char *psz_filename, hnd_t *p_handle )
678 if( !(p_mp4 = malloc(sizeof(mp4_t))) )
681 memset( p_mp4, 0, sizeof(mp4_t) );
682 p_mp4->p_file = gf_isom_open( psz_filename, GF_ISOM_OPEN_WRITE, NULL );
684 if( !(p_mp4->p_sample = gf_isom_sample_new()) )
686 close_file_mp4( p_mp4 );
690 gf_isom_set_brand_info( p_mp4->p_file, GF_ISOM_BRAND_AVC1, 0 );
698 int set_param_mp4( hnd_t handle, x264_param_t *p_param )
700 mp4_t *p_mp4 = (mp4_t*)handle;
702 p_mp4->i_track = gf_isom_new_track( p_mp4->p_file, 0, GF_ISOM_MEDIA_VISUAL,
703 p_param->i_fps_num );
705 p_mp4->p_config = gf_odf_avc_cfg_new();
706 gf_isom_avc_config_new( p_mp4->p_file, p_mp4->i_track, p_mp4->p_config,
707 NULL, NULL, &p_mp4->i_descidx );
709 gf_isom_set_track_enabled( p_mp4->p_file, p_mp4->i_track, 1 );
711 gf_isom_set_visual_info( p_mp4->p_file, p_mp4->i_track, p_mp4->i_descidx,
712 p_param->i_width, p_param->i_height );
714 if( p_param->vui.i_sar_width && p_param->vui.i_sar_height )
716 uint64_t dw = p_param->i_width << 16;
717 uint64_t dh = p_param->i_height << 16;
718 double sar = (double)p_param->vui.i_sar_width / p_param->vui.i_sar_height;
723 gf_isom_set_track_layout_info( p_mp4->p_file, p_mp4->i_track, dw, dh, 0, 0, 0 );
726 p_mp4->p_sample->data = malloc( p_param->i_width * p_param->i_height * 3 / 2 );
727 if( !p_mp4->p_sample->data )
730 p_mp4->i_time_res = p_param->i_fps_num;
731 p_mp4->i_time_inc = p_param->i_fps_den;
732 p_mp4->i_init_delay = p_param->i_bframe ? (p_param->b_bframe_pyramid ? 2 : 1) : 0;
733 p_mp4->i_init_delay *= p_mp4->i_time_inc;
734 fprintf( stderr, "mp4 [info]: initial delay %d (scale %d)\n",
735 p_mp4->i_init_delay, p_mp4->i_time_res );
741 int write_nalu_mp4( hnd_t handle, uint8_t *p_nalu, int i_size )
743 mp4_t *p_mp4 = (mp4_t*)handle;
744 GF_AVCConfigSlot *p_slot;
745 uint8_t type = p_nalu[4] & 0x1f;
754 p_mp4->p_config->configurationVersion = 1;
755 p_mp4->p_config->AVCProfileIndication = p_nalu[5];
756 p_mp4->p_config->profile_compatibility = p_nalu[6];
757 p_mp4->p_config->AVCLevelIndication = p_nalu[7];
758 p_slot = malloc( sizeof(GF_AVCConfigSlot) );
761 p_slot->size = i_size - 4;
762 p_slot->data = malloc( p_slot->size );
765 memcpy( p_slot->data, p_nalu + 4, i_size - 4 );
766 gf_list_add( p_mp4->p_config->sequenceParameterSets, p_slot );
776 p_slot = malloc( sizeof(GF_AVCConfigSlot) );
779 p_slot->size = i_size - 4;
780 p_slot->data = malloc( p_slot->size );
783 memcpy( p_slot->data, p_nalu + 4, i_size - 4 );
784 gf_list_add( p_mp4->p_config->pictureParameterSets, p_slot );
788 gf_isom_avc_config_update( p_mp4->p_file, p_mp4->i_track, 1, p_mp4->p_config );
797 memcpy( p_mp4->p_sample->data + p_mp4->p_sample->dataLength, p_nalu, i_size );
798 p_mp4->p_sample->data[p_mp4->p_sample->dataLength + 0] = psize >> 24;
799 p_mp4->p_sample->data[p_mp4->p_sample->dataLength + 1] = psize >> 16;
800 p_mp4->p_sample->data[p_mp4->p_sample->dataLength + 2] = psize >> 8;
801 p_mp4->p_sample->data[p_mp4->p_sample->dataLength + 3] = psize >> 0;
802 p_mp4->p_sample->dataLength += i_size;
809 int set_eop_mp4( hnd_t handle, x264_picture_t *p_picture )
811 mp4_t *p_mp4 = (mp4_t*)handle;
812 uint64_t dts = (uint64_t)p_mp4->i_numframe * p_mp4->i_time_inc;
813 uint64_t pts = (uint64_t)p_picture->i_pts;
814 int32_t offset = p_mp4->i_init_delay + pts - dts;
816 p_mp4->p_sample->IsRAP = p_picture->i_type == X264_TYPE_IDR ? 1 : 0;
817 p_mp4->p_sample->DTS = dts;
818 p_mp4->p_sample->CTS_Offset = offset;
819 gf_isom_add_sample( p_mp4->p_file, p_mp4->i_track, p_mp4->i_descidx, p_mp4->p_sample );
821 p_mp4->p_sample->dataLength = 0;
830 /* -- mkv muxing support ------------------------------------------------- */
836 int sps_len, pps_len;
838 int width, height, d_width, d_height;
840 int64_t frame_duration;
843 int b_header_written;
844 char b_writing_frame;
847 static int write_header_mkv( mkv_t *p_mkv )
853 if( !p_mkv->sps || !p_mkv->pps ||
854 !p_mkv->width || !p_mkv->height ||
855 !p_mkv->d_width || !p_mkv->d_height )
858 avcC_len = 5 + 1 + 2 + p_mkv->sps_len + 1 + 2 + p_mkv->pps_len;
859 avcC = malloc( avcC_len );
864 avcC[1] = p_mkv->sps[1];
865 avcC[2] = p_mkv->sps[2];
866 avcC[3] = p_mkv->sps[3];
867 avcC[4] = 0xff; // nalu size length is four bytes
868 avcC[5] = 0xe1; // one sps
870 avcC[6] = p_mkv->sps_len >> 8;
871 avcC[7] = p_mkv->sps_len;
873 memcpy( avcC+8, p_mkv->sps, p_mkv->sps_len );
875 avcC[8+p_mkv->sps_len] = 1; // one pps
876 avcC[9+p_mkv->sps_len] = p_mkv->pps_len >> 8;
877 avcC[10+p_mkv->sps_len] = p_mkv->pps_len;
879 memcpy( avcC+11+p_mkv->sps_len, p_mkv->pps, p_mkv->pps_len );
881 ret = mk_writeHeader( p_mkv->w, "x264", "V_MPEG4/ISO/AVC",
882 avcC, avcC_len, p_mkv->frame_duration, 50000,
883 p_mkv->width, p_mkv->height,
884 p_mkv->d_width, p_mkv->d_height );
888 p_mkv->b_header_written = 1;
893 int open_file_mkv( char *psz_filename, hnd_t *p_handle )
899 p_mkv = malloc( sizeof(*p_mkv) );
903 memset( p_mkv, 0, sizeof(*p_mkv) );
905 p_mkv->w = mk_create_writer( psz_filename );
917 int set_param_mkv( hnd_t handle, x264_param_t *p_param )
919 mkv_t *p_mkv = handle;
922 if( p_param->i_fps_num > 0 )
924 p_mkv->frame_duration = (int64_t)p_param->i_fps_den *
925 (int64_t)1000000000 / p_param->i_fps_num;
926 p_mkv->fps_num = p_param->i_fps_num;
930 p_mkv->frame_duration = 0;
934 p_mkv->width = p_param->i_width;
935 p_mkv->height = p_param->i_height;
937 if( p_param->vui.i_sar_width && p_param->vui.i_sar_height )
939 dw = (int64_t)p_param->i_width * p_param->vui.i_sar_width;
940 dh = (int64_t)p_param->i_height * p_param->vui.i_sar_height;
944 dw = p_param->i_width;
945 dh = p_param->i_height;
948 if( dw > 0 && dh > 0 )
950 int64_t x = gcd( dw, dh );
955 p_mkv->d_width = (int)dw;
956 p_mkv->d_height = (int)dh;
961 int write_nalu_mkv( hnd_t handle, uint8_t *p_nalu, int i_size )
963 mkv_t *p_mkv = handle;
964 uint8_t type = p_nalu[4] & 0x1f;
974 p_mkv->sps = malloc( i_size - 4 );
977 p_mkv->sps_len = i_size - 4;
978 memcpy( p_mkv->sps, p_nalu + 4, i_size - 4 );
986 p_mkv->pps = malloc( i_size - 4 );
989 p_mkv->pps_len = i_size - 4;
990 memcpy( p_mkv->pps, p_nalu + 4, i_size - 4 );
998 if( !p_mkv->b_writing_frame )
1000 if( mk_start_frame( p_mkv->w ) < 0 )
1002 p_mkv->b_writing_frame = 1;
1004 psize = i_size - 4 ;
1005 dsize[0] = psize >> 24;
1006 dsize[1] = psize >> 16;
1007 dsize[2] = psize >> 8;
1009 if( mk_add_frame_data( p_mkv->w, dsize, 4 ) < 0 ||
1010 mk_add_frame_data( p_mkv->w, p_nalu + 4, i_size - 4 ) < 0 )
1018 if( !p_mkv->b_header_written && p_mkv->pps && p_mkv->sps &&
1019 write_header_mkv( p_mkv ) < 0 )
1025 int set_eop_mkv( hnd_t handle, x264_picture_t *p_picture )
1027 mkv_t *p_mkv = handle;
1028 int64_t i_stamp = (int64_t)(p_picture->i_pts * 1e9 / p_mkv->fps_num);
1030 p_mkv->b_writing_frame = 0;
1032 return mk_set_frame_flags( p_mkv->w, i_stamp, p_picture->i_type == X264_TYPE_IDR );
1035 int close_file_mkv( hnd_t handle )
1037 mkv_t *p_mkv = handle;
1045 ret = mk_close( p_mkv->w );