muxers.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:26k
源码类别:

Audio

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * muxers.c: h264 file i/o plugins
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2008 x264 project
  5.  *
  6.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  7.  *          Loren Merritt <lorenm@u.washington.edu>
  8.  *
  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.
  13.  *
  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.
  18.  *
  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.  *****************************************************************************/
  23. #include "common/common.h"
  24. #include "x264.h"
  25. #include "matroska.h"
  26. #include "muxers.h"
  27. #ifndef _MSC_VER
  28. #include "config.h"
  29. #endif
  30. #include <sys/types.h>
  31. #ifdef AVIS_INPUT
  32. #include <windows.h>
  33. #include <vfw.h>
  34. #endif
  35. #ifdef MP4_OUTPUT
  36. #include <gpac/isomedia.h>
  37. #endif
  38. static int64_t gcd( int64_t a, int64_t b )
  39. {
  40.     while (1)
  41.     {
  42.         int64_t c = a % b;
  43.         if( !c )
  44.             return b;
  45.         a = b;
  46.         b = c;
  47.     }
  48. }
  49. typedef struct {
  50.     FILE *fh;
  51.     int width, height;
  52.     int next_frame;
  53. } yuv_input_t;
  54. /* raw 420 yuv file operation */
  55. int open_file_yuv( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
  56. {
  57.     yuv_input_t *h = malloc(sizeof(yuv_input_t));
  58.     h->width = p_param->i_width;
  59.     h->height = p_param->i_height;
  60.     h->next_frame = 0;
  61.     if( !strcmp(psz_filename, "-") )
  62.         h->fh = stdin;
  63.     else
  64.         h->fh = fopen(psz_filename, "rb");
  65.     if( h->fh == NULL )
  66.         return -1;
  67.     *p_handle = (hnd_t)h;
  68.     return 0;
  69. }
  70. int get_frame_total_yuv( hnd_t handle )
  71. {
  72.     yuv_input_t *h = handle;
  73.     int i_frame_total = 0;
  74.     if( !fseek( h->fh, 0, SEEK_END ) )
  75.     {
  76.         uint64_t i_size = ftell( h->fh );
  77.         fseek( h->fh, 0, SEEK_SET );
  78.         i_frame_total = (int)(i_size / ( h->width * h->height * 3 / 2 ));
  79.     }
  80.     return i_frame_total;
  81. }
  82. int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame )
  83. {
  84.     yuv_input_t *h = handle;
  85.     if( i_frame != h->next_frame )
  86.         if( fseek( h->fh, (uint64_t)i_frame * h->width * h->height * 3 / 2, SEEK_SET ) )
  87.             return -1;
  88.     if( fread( p_pic->img.plane[0], 1, h->width * h->height, h->fh ) <= 0
  89.             || fread( p_pic->img.plane[1], 1, h->width * h->height / 4, h->fh ) <= 0
  90.             || fread( p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh ) <= 0 )
  91.         return -1;
  92.     h->next_frame = i_frame+1;
  93.     return 0;
  94. }
  95. int close_file_yuv(hnd_t handle)
  96. {
  97.     yuv_input_t *h = handle;
  98.     if( !h || !h->fh )
  99.         return 0;
  100.     fclose( h->fh );
  101.     free( h );
  102.     return 0;
  103. }
  104. /* YUV4MPEG2 raw 420 yuv file operation */
  105. typedef struct {
  106.     FILE *fh;
  107.     int width, height;
  108.     int next_frame;
  109.     int seq_header_len, frame_header_len;
  110.     int frame_size;
  111. } y4m_input_t;
  112. #define Y4M_MAGIC "YUV4MPEG2"
  113. #define MAX_YUV4_HEADER 80
  114. #define Y4M_FRAME_MAGIC "FRAME"
  115. #define MAX_FRAME_HEADER 80
  116. int open_file_y4m( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
  117. {
  118.     int  i, n, d;
  119.     int  interlaced;
  120.     char header[MAX_YUV4_HEADER+10];
  121.     char *tokstart, *tokend, *header_end;
  122.     y4m_input_t *h = malloc(sizeof(y4m_input_t));
  123.     h->next_frame = 0;
  124.     if( !strcmp(psz_filename, "-") )
  125.         h->fh = stdin;
  126.     else
  127.         h->fh = fopen(psz_filename, "rb");
  128.     if( h->fh == NULL )
  129.         return -1;
  130.     h->frame_header_len = strlen(Y4M_FRAME_MAGIC)+1;
  131.     /* Read header */
  132.     for( i=0; i<MAX_YUV4_HEADER; i++ )
  133.     {
  134.         header[i] = fgetc(h->fh);
  135.         if( header[i] == 'n' )
  136.         {
  137.             /* Add a space after last option. Makes parsing "444" vs
  138.                "444alpha" easier. */
  139.             header[i+1] = 0x20;
  140.             header[i+2] = 0;
  141.             break;
  142.         }
  143.     }
  144.     if( i == MAX_YUV4_HEADER || strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC)) )
  145.         return -1;
  146.     /* Scan properties */
  147.     header_end = &header[i+1]; /* Include space */
  148.     h->seq_header_len = i+1;
  149.     for( tokstart = &header[strlen(Y4M_MAGIC)+1]; tokstart < header_end; tokstart++ )
  150.     {
  151.         if(*tokstart==0x20) continue;
  152.         switch(*tokstart++)
  153.         {
  154.         case 'W': /* Width. Required. */
  155.             h->width = p_param->i_width = strtol(tokstart, &tokend, 10);
  156.             tokstart=tokend;
  157.             break;
  158.         case 'H': /* Height. Required. */
  159.             h->height = p_param->i_height = strtol(tokstart, &tokend, 10);
  160.             tokstart=tokend;
  161.             break;
  162.         case 'C': /* Color space */
  163.             if( strncmp("420", tokstart, 3) )
  164.             {
  165.                 fprintf(stderr, "Colorspace unhandledn");
  166.                 return -1;
  167.             }
  168.             tokstart = strchr(tokstart, 0x20);
  169.             break;
  170.         case 'I': /* Interlace type */
  171.             switch(*tokstart++)
  172.             {
  173.             case 'p': interlaced = 0; break;
  174.             case '?':
  175.             case 't':
  176.             case 'b':
  177.             case 'm':
  178.             default: interlaced = 1;
  179.                 fprintf(stderr, "Warning, this sequence might be interlacedn");
  180.             }
  181.             break;
  182.         case 'F': /* Frame rate - 0:0 if unknown */
  183.             if( sscanf(tokstart, "%d:%d", &n, &d) == 2 && n && d )
  184.             {
  185.                 x264_reduce_fraction( &n, &d );
  186.                 p_param->i_fps_num = n;
  187.                 p_param->i_fps_den = d;
  188.             }
  189.             tokstart = strchr(tokstart, 0x20);
  190.             break;
  191.         case 'A': /* Pixel aspect - 0:0 if unknown */
  192.             if( sscanf(tokstart, "%d:%d", &n, &d) == 2 && n && d )
  193.             {
  194.                 x264_reduce_fraction( &n, &d );
  195.                 p_param->vui.i_sar_width = n;
  196.                 p_param->vui.i_sar_height = d;
  197.             }
  198.             tokstart = strchr(tokstart, 0x20);
  199.             break;
  200.         case 'X': /* Vendor extensions */
  201.             if( !strncmp("YSCSS=",tokstart,6) )
  202.             {
  203.                 /* Older nonstandard pixel format representation */
  204.                 tokstart += 6;
  205.                 if( strncmp("420JPEG",tokstart,7) &&
  206.                     strncmp("420MPEG2",tokstart,8) &&
  207.                     strncmp("420PALDV",tokstart,8) )
  208.                 {
  209.                     fprintf(stderr, "Unsupported extended colorspacen");
  210.                     return -1;
  211.                 }
  212.             }
  213.             tokstart = strchr(tokstart, 0x20);
  214.             break;
  215.         }
  216.     }
  217.     fprintf(stderr, "yuv4mpeg: %ix%i@%i/%ifps, %i:%in",
  218.             h->width, h->height, p_param->i_fps_num, p_param->i_fps_den,
  219.             p_param->vui.i_sar_width, p_param->vui.i_sar_height);
  220.     *p_handle = (hnd_t)h;
  221.     return 0;
  222. }
  223. /* Most common case: frame_header = "FRAME" */
  224. int get_frame_total_y4m( hnd_t handle )
  225. {
  226.     y4m_input_t *h             = handle;
  227.     int          i_frame_total = 0;
  228.     uint64_t     init_pos      = ftell(h->fh);
  229.     if( !fseek( h->fh, 0, SEEK_END ) )
  230.     {
  231.         uint64_t i_size = ftell( h->fh );
  232.         fseek( h->fh, init_pos, SEEK_SET );
  233.         i_frame_total = (int)((i_size - h->seq_header_len) /
  234.                               (3*(h->width*h->height)/2+h->frame_header_len));
  235.     }
  236.     return i_frame_total;
  237. }
  238. int read_frame_y4m( x264_picture_t *p_pic, hnd_t handle, int i_frame )
  239. {
  240.     int          slen = strlen(Y4M_FRAME_MAGIC);
  241.     int          i    = 0;
  242.     char         header[16];
  243.     y4m_input_t *h    = handle;
  244.     if( i_frame != h->next_frame )
  245.     {
  246.         if (fseek(h->fh, (uint64_t)i_frame*(3*(h->width*h->height)/2+h->frame_header_len)
  247.                   + h->seq_header_len, SEEK_SET))
  248.             return -1;
  249.     }
  250.     /* Read frame header - without terminating 'n' */
  251.     if (fread(header, 1, slen, h->fh) != slen)
  252.         return -1;
  253.     header[slen] = 0;
  254.     if (strncmp(header, Y4M_FRAME_MAGIC, slen))
  255.     {
  256.         fprintf(stderr, "Bad header magic (%08X <=> %s)n",
  257.                 *((uint32_t*)header), header);
  258.         return -1;
  259.     }
  260.     /* Skip most of it */
  261.     while (i<MAX_FRAME_HEADER && fgetc(h->fh) != 'n')
  262.         i++;
  263.     if (i == MAX_FRAME_HEADER)
  264.     {
  265.         fprintf(stderr, "Bad frame header!n");
  266.         return -1;
  267.     }
  268.     h->frame_header_len = i+slen+1;
  269.     if( fread(p_pic->img.plane[0], 1, h->width*h->height, h->fh) <= 0
  270.         || fread(p_pic->img.plane[1], 1, h->width * h->height / 4, h->fh) <= 0
  271.         || fread(p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh) <= 0)
  272.         return -1;
  273.     h->next_frame = i_frame+1;
  274.     return 0;
  275. }
  276. int close_file_y4m(hnd_t handle)
  277. {
  278.     y4m_input_t *h = handle;
  279.     if( !h || !h->fh )
  280.         return 0;
  281.     fclose( h->fh );
  282.     free( h );
  283.     return 0;
  284. }
  285. /* avs/avi input file support under cygwin */
  286. #ifdef AVIS_INPUT
  287. typedef struct {
  288.     PAVISTREAM p_avi;
  289.     int width, height;
  290. } avis_input_t;
  291. int open_file_avis( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
  292. {
  293.     avis_input_t *h = malloc(sizeof(avis_input_t));
  294.     AVISTREAMINFO info;
  295.     int i;
  296.     *p_handle = (hnd_t)h;
  297.     AVIFileInit();
  298.     if( AVIStreamOpenFromFile( &h->p_avi, psz_filename, streamtypeVIDEO, 0, OF_READ, NULL ) )
  299.     {
  300.         AVIFileExit();
  301.         return -1;
  302.     }
  303.     if( AVIStreamInfo(h->p_avi, &info, sizeof(AVISTREAMINFO)) )
  304.     {
  305.         AVIStreamRelease(h->p_avi);
  306.         AVIFileExit();
  307.         return -1;
  308.     }
  309.     // check input format
  310.     if (info.fccHandler != MAKEFOURCC('Y', 'V', '1', '2'))
  311.     {
  312.         fprintf( stderr, "avis [error]: unsupported input format (%c%c%c%c)n",
  313.             (char)(info.fccHandler & 0xff), (char)((info.fccHandler >> 8) & 0xff),
  314.             (char)((info.fccHandler >> 16) & 0xff), (char)((info.fccHandler >> 24)) );
  315.         AVIStreamRelease(h->p_avi);
  316.         AVIFileExit();
  317.         return -1;
  318.     }
  319.     h->width =
  320.     p_param->i_width = info.rcFrame.right - info.rcFrame.left;
  321.     h->height =
  322.     p_param->i_height = info.rcFrame.bottom - info.rcFrame.top;
  323.     i = gcd(info.dwRate, info.dwScale);
  324.     p_param->i_fps_den = info.dwScale / i;
  325.     p_param->i_fps_num = info.dwRate / i;
  326.     fprintf( stderr, "avis [info]: %dx%d @ %.2f fps (%d frames)n",
  327.         p_param->i_width, p_param->i_height,
  328.         (double)p_param->i_fps_num / (double)p_param->i_fps_den,
  329.         (int)info.dwLength );
  330.     return 0;
  331. }
  332. int get_frame_total_avis( hnd_t handle )
  333. {
  334.     avis_input_t *h = handle;
  335.     AVISTREAMINFO info;
  336.     if( AVIStreamInfo(h->p_avi, &info, sizeof(AVISTREAMINFO)) )
  337.         return -1;
  338.     return info.dwLength;
  339. }
  340. int read_frame_avis( x264_picture_t *p_pic, hnd_t handle, int i_frame )
  341. {
  342.     avis_input_t *h = handle;
  343.     p_pic->img.i_csp = X264_CSP_YV12;
  344.     if( AVIStreamRead(h->p_avi, i_frame, 1, p_pic->img.plane[0], h->width * h->height * 3 / 2, NULL, NULL ) )
  345.         return -1;
  346.     return 0;
  347. }
  348. int close_file_avis( hnd_t handle )
  349. {
  350.     avis_input_t *h = handle;
  351.     AVIStreamRelease(h->p_avi);
  352.     AVIFileExit();
  353.     free(h);
  354.     return 0;
  355. }
  356. #endif
  357. #ifdef HAVE_PTHREAD
  358. typedef struct {
  359.     int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame );
  360.     int (*p_close_infile)( hnd_t handle );
  361.     hnd_t p_handle;
  362.     x264_picture_t pic;
  363.     x264_pthread_t tid;
  364.     int next_frame;
  365.     int frame_total;
  366.     int in_progress;
  367.     struct thread_input_arg_t *next_args;
  368. } thread_input_t;
  369. typedef struct thread_input_arg_t {
  370.     thread_input_t *h;
  371.     x264_picture_t *pic;
  372.     int i_frame;
  373.     int status;
  374. } thread_input_arg_t;
  375. int open_file_thread( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
  376. {
  377.     thread_input_t *h = malloc(sizeof(thread_input_t));
  378.     x264_picture_alloc( &h->pic, X264_CSP_I420, p_param->i_width, p_param->i_height );
  379.     h->p_read_frame = p_read_frame;
  380.     h->p_close_infile = p_close_infile;
  381.     h->p_handle = *p_handle;
  382.     h->in_progress = 0;
  383.     h->next_frame = -1;
  384.     h->next_args = malloc(sizeof(thread_input_arg_t));
  385.     h->next_args->h = h;
  386.     h->next_args->status = 0;
  387.     h->frame_total = p_get_frame_total( h->p_handle );
  388.     *p_handle = (hnd_t)h;
  389.     return 0;
  390. }
  391. int get_frame_total_thread( hnd_t handle )
  392. {
  393.     thread_input_t *h = handle;
  394.     return h->frame_total;
  395. }
  396. static void read_frame_thread_int( thread_input_arg_t *i )
  397. {
  398.     i->status = i->h->p_read_frame( i->pic, i->h->p_handle, i->i_frame );
  399. }
  400. int read_frame_thread( x264_picture_t *p_pic, hnd_t handle, int i_frame )
  401. {
  402.     thread_input_t *h = handle;
  403.     UNUSED void *stuff;
  404.     int ret = 0;
  405.     if( h->next_frame >= 0 )
  406.     {
  407.         x264_pthread_join( h->tid, &stuff );
  408.         ret |= h->next_args->status;
  409.         h->in_progress = 0;
  410.     }
  411.     if( h->next_frame == i_frame )
  412.     {
  413.         XCHG( x264_picture_t, *p_pic, h->pic );
  414.     }
  415.     else
  416.     {
  417.         ret |= h->p_read_frame( p_pic, h->p_handle, i_frame );
  418.     }
  419.     if( !h->frame_total || i_frame+1 < h->frame_total )
  420.     {
  421.         h->next_frame =
  422.         h->next_args->i_frame = i_frame+1;
  423.         h->next_args->pic = &h->pic;
  424.         x264_pthread_create( &h->tid, NULL, (void*)read_frame_thread_int, h->next_args );
  425.         h->in_progress = 1;
  426.     }
  427.     else
  428.         h->next_frame = -1;
  429.     return ret;
  430. }
  431. int close_file_thread( hnd_t handle )
  432. {
  433.     thread_input_t *h = handle;
  434.     h->p_close_infile( h->p_handle );
  435.     x264_picture_clean( &h->pic );
  436.     if( h->in_progress )
  437.         x264_pthread_join( h->tid, NULL );
  438.     free( h->next_args );
  439.     free( h );
  440.     return 0;
  441. }
  442. #endif
  443. int open_file_bsf( char *psz_filename, hnd_t *p_handle )
  444. {
  445.     if ((*p_handle = fopen(psz_filename, "w+b")) == NULL)
  446.         return -1;
  447.     return 0;
  448. }
  449. int set_param_bsf( hnd_t handle, x264_param_t *p_param )
  450. {
  451.     return 0;
  452. }
  453. int write_nalu_bsf( hnd_t handle, uint8_t *p_nalu, int i_size )
  454. {
  455.     if (fwrite(p_nalu, i_size, 1, (FILE *)handle) > 0)
  456.         return i_size;
  457.     return -1;
  458. }
  459. int set_eop_bsf( hnd_t handle,  x264_picture_t *p_picture )
  460. {
  461.     return 0;
  462. }
  463. int close_file_bsf( hnd_t handle )
  464. {
  465.     if ((handle == NULL) || (handle == stdout))
  466.         return 0;
  467.     return fclose((FILE *)handle);
  468. }
  469. /* -- mp4 muxing support ------------------------------------------------- */
  470. #ifdef MP4_OUTPUT
  471. typedef struct
  472. {
  473.     GF_ISOFile *p_file;
  474.     GF_AVCConfig *p_config;
  475.     GF_ISOSample *p_sample;
  476.     int i_track;
  477.     uint32_t i_descidx;
  478.     int i_time_inc;
  479.     int i_time_res;
  480.     int i_numframe;
  481.     int i_init_delay;
  482.     uint8_t b_sps;
  483.     uint8_t b_pps;
  484. } mp4_t;
  485. static void recompute_bitrate_mp4(GF_ISOFile *p_file, int i_track)
  486. {
  487.     u32 i, count, di, timescale, time_wnd, rate;
  488.     u64 offset;
  489.     Double br;
  490.     GF_ESD *esd;
  491.     esd = gf_isom_get_esd(p_file, i_track, 1);
  492.     if (!esd) return;
  493.     esd->decoderConfig->avgBitrate = 0;
  494.     esd->decoderConfig->maxBitrate = 0;
  495.     rate = time_wnd = 0;
  496.     timescale = gf_isom_get_media_timescale(p_file, i_track);
  497.     count = gf_isom_get_sample_count(p_file, i_track);
  498.     for (i=0; i<count; i++) {
  499.         GF_ISOSample *samp = gf_isom_get_sample_info(p_file, i_track, i+1, &di, &offset);
  500.         if (samp->dataLength>esd->decoderConfig->bufferSizeDB) esd->decoderConfig->bufferSizeDB = samp->dataLength;
  501.         if (esd->decoderConfig->bufferSizeDB < samp->dataLength) esd->decoderConfig->bufferSizeDB = samp->dataLength;
  502.         esd->decoderConfig->avgBitrate += samp->dataLength;
  503.         rate += samp->dataLength;
  504.         if (samp->DTS > time_wnd + timescale) {
  505.             if (rate > esd->decoderConfig->maxBitrate) esd->decoderConfig->maxBitrate = rate;
  506.             time_wnd = samp->DTS;
  507.             rate = 0;
  508.         }
  509.         gf_isom_sample_del(&samp);
  510.     }
  511.     br = (Double) (s64) gf_isom_get_media_duration(p_file, i_track);
  512.     br /= timescale;
  513.     esd->decoderConfig->avgBitrate = (u32) (esd->decoderConfig->avgBitrate / br);
  514.     /*move to bps*/
  515.     esd->decoderConfig->avgBitrate *= 8;
  516.     esd->decoderConfig->maxBitrate *= 8;
  517.     gf_isom_change_mpeg4_description(p_file, i_track, 1, esd);
  518.     gf_odf_desc_del((GF_Descriptor *) esd);
  519. }
  520. int close_file_mp4( hnd_t handle )
  521. {
  522.     mp4_t *p_mp4 = (mp4_t *)handle;
  523.     if (p_mp4 == NULL)
  524.         return 0;
  525.     if (p_mp4->p_config)
  526.         gf_odf_avc_cfg_del(p_mp4->p_config);
  527.     if (p_mp4->p_sample)
  528.     {
  529.         if (p_mp4->p_sample->data)
  530.             free(p_mp4->p_sample->data);
  531.         gf_isom_sample_del(&p_mp4->p_sample);
  532.     }
  533.     if (p_mp4->p_file)
  534.     {
  535.         recompute_bitrate_mp4(p_mp4->p_file, p_mp4->i_track);
  536.         gf_isom_set_pl_indication(p_mp4->p_file, GF_ISOM_PL_VISUAL, 0x15);
  537.         gf_isom_set_storage_mode(p_mp4->p_file, GF_ISOM_STORE_FLAT);
  538.         gf_isom_close(p_mp4->p_file);
  539.     }
  540.     free(p_mp4);
  541.     return 0;
  542. }
  543. int open_file_mp4( char *psz_filename, hnd_t *p_handle )
  544. {
  545.     mp4_t *p_mp4;
  546.     *p_handle = NULL;
  547.     if ((p_mp4 = (mp4_t *)malloc(sizeof(mp4_t))) == NULL)
  548.         return -1;
  549.     memset(p_mp4, 0, sizeof(mp4_t));
  550.     p_mp4->p_file = gf_isom_open(psz_filename, GF_ISOM_OPEN_WRITE, NULL);
  551.     if ((p_mp4->p_sample = gf_isom_sample_new()) == NULL)
  552.     {
  553.         close_file_mp4( p_mp4 );
  554.         return -1;
  555.     }
  556.     gf_isom_set_brand_info(p_mp4->p_file, GF_ISOM_BRAND_AVC1, 0);
  557.     *p_handle = p_mp4;
  558.     return 0;
  559. }
  560. int set_param_mp4( hnd_t handle, x264_param_t *p_param )
  561. {
  562.     mp4_t *p_mp4 = (mp4_t *)handle;
  563.     p_mp4->i_track = gf_isom_new_track(p_mp4->p_file, 0, GF_ISOM_MEDIA_VISUAL,
  564.         p_param->i_fps_num);
  565.     p_mp4->p_config = gf_odf_avc_cfg_new();
  566.     gf_isom_avc_config_new(p_mp4->p_file, p_mp4->i_track, p_mp4->p_config,
  567.         NULL, NULL, &p_mp4->i_descidx);
  568.     gf_isom_set_track_enabled(p_mp4->p_file, p_mp4->i_track, 1);
  569.     gf_isom_set_visual_info(p_mp4->p_file, p_mp4->i_track, p_mp4->i_descidx,
  570.         p_param->i_width, p_param->i_height);
  571.     if( p_param->vui.i_sar_width && p_param->vui.i_sar_height )
  572.     {
  573.         uint64_t dw = p_param->i_width << 16;
  574.         uint64_t dh = p_param->i_height << 16;
  575.         double sar = (double)p_param->vui.i_sar_width / p_param->vui.i_sar_height;
  576.         if( sar > 1.0 )
  577.             dw *= sar ;
  578.         else
  579.             dh /= sar;
  580.         gf_isom_set_track_layout_info( p_mp4->p_file, p_mp4->i_track, dw, dh, 0, 0, 0 );
  581.     }
  582.     p_mp4->p_sample->data = (char *)malloc(p_param->i_width * p_param->i_height * 3 / 2);
  583.     if (p_mp4->p_sample->data == NULL)
  584.         return -1;
  585.     p_mp4->i_time_res = p_param->i_fps_num;
  586.     p_mp4->i_time_inc = p_param->i_fps_den;
  587.     p_mp4->i_init_delay = p_param->i_bframe ? (p_param->b_bframe_pyramid ? 2 : 1) : 0;
  588.     p_mp4->i_init_delay *= p_mp4->i_time_inc;
  589.     fprintf(stderr, "mp4 [info]: initial delay %d (scale %d)n",
  590.         p_mp4->i_init_delay, p_mp4->i_time_res);
  591.     return 0;
  592. }
  593. int write_nalu_mp4( hnd_t handle, uint8_t *p_nalu, int i_size )
  594. {
  595.     mp4_t *p_mp4 = (mp4_t *)handle;
  596.     GF_AVCConfigSlot *p_slot;
  597.     uint8_t type = p_nalu[4] & 0x1f;
  598.     int psize;
  599.     switch(type)
  600.     {
  601.     // sps
  602.     case 0x07:
  603.         if (!p_mp4->b_sps)
  604.         {
  605.             p_mp4->p_config->configurationVersion = 1;
  606.             p_mp4->p_config->AVCProfileIndication = p_nalu[5];
  607.             p_mp4->p_config->profile_compatibility = p_nalu[6];
  608.             p_mp4->p_config->AVCLevelIndication = p_nalu[7];
  609.             p_slot = (GF_AVCConfigSlot *)malloc(sizeof(GF_AVCConfigSlot));
  610.             p_slot->size = i_size - 4;
  611.             p_slot->data = (char *)malloc(p_slot->size);
  612.             memcpy(p_slot->data, p_nalu + 4, i_size - 4);
  613.             gf_list_add(p_mp4->p_config->sequenceParameterSets, p_slot);
  614.             p_slot = NULL;
  615.             p_mp4->b_sps = 1;
  616.         }
  617.         break;
  618.     // pps
  619.     case 0x08:
  620.         if (!p_mp4->b_pps)
  621.         {
  622.             p_slot = (GF_AVCConfigSlot *)malloc(sizeof(GF_AVCConfigSlot));
  623.             p_slot->size = i_size - 4;
  624.             p_slot->data = (char *)malloc(p_slot->size);
  625.             memcpy(p_slot->data, p_nalu + 4, i_size - 4);
  626.             gf_list_add(p_mp4->p_config->pictureParameterSets, p_slot);
  627.             p_slot = NULL;
  628.             p_mp4->b_pps = 1;
  629.             if (p_mp4->b_sps)
  630.                 gf_isom_avc_config_update(p_mp4->p_file, p_mp4->i_track, 1, p_mp4->p_config);
  631.         }
  632.         break;
  633.     // slice, sei
  634.     case 0x1:
  635.     case 0x5:
  636.     case 0x6:
  637.         psize = i_size - 4 ;
  638.         memcpy(p_mp4->p_sample->data + p_mp4->p_sample->dataLength, p_nalu, i_size);
  639.         p_mp4->p_sample->data[p_mp4->p_sample->dataLength + 0] = (psize >> 24) & 0xff;
  640.         p_mp4->p_sample->data[p_mp4->p_sample->dataLength + 1] = (psize >> 16) & 0xff;
  641.         p_mp4->p_sample->data[p_mp4->p_sample->dataLength + 2] = (psize >> 8) & 0xff;
  642.         p_mp4->p_sample->data[p_mp4->p_sample->dataLength + 3] = (psize >> 0) & 0xff;
  643.         p_mp4->p_sample->dataLength += i_size;
  644.         break;
  645.     }
  646.     return i_size;
  647. }
  648. int set_eop_mp4( hnd_t handle, x264_picture_t *p_picture )
  649. {
  650.     mp4_t *p_mp4 = (mp4_t *)handle;
  651.     uint64_t dts = (uint64_t)p_mp4->i_numframe * p_mp4->i_time_inc;
  652.     uint64_t pts = (uint64_t)p_picture->i_pts;
  653.     int32_t offset = p_mp4->i_init_delay + pts - dts;
  654.     p_mp4->p_sample->IsRAP = p_picture->i_type == X264_TYPE_IDR ? 1 : 0;
  655.     p_mp4->p_sample->DTS = dts;
  656.     p_mp4->p_sample->CTS_Offset = offset;
  657.     gf_isom_add_sample(p_mp4->p_file, p_mp4->i_track, p_mp4->i_descidx, p_mp4->p_sample);
  658.     p_mp4->p_sample->dataLength = 0;
  659.     p_mp4->i_numframe++;
  660.     return 0;
  661. }
  662. #endif
  663. /* -- mkv muxing support ------------------------------------------------- */
  664. typedef struct
  665. {
  666.     mk_Writer *w;
  667.     uint8_t   *sps, *pps;
  668.     int       sps_len, pps_len;
  669.     int       width, height, d_width, d_height;
  670.     int64_t   frame_duration;
  671.     int       fps_num;
  672.     int       b_header_written;
  673.     char      b_writing_frame;
  674. } mkv_t;
  675. static int write_header_mkv( mkv_t *p_mkv )
  676. {
  677.     int       ret;
  678.     uint8_t   *avcC;
  679.     int  avcC_len;
  680.     if( p_mkv->sps == NULL || p_mkv->pps == NULL ||
  681.         p_mkv->width == 0 || p_mkv->height == 0 ||
  682.         p_mkv->d_width == 0 || p_mkv->d_height == 0)
  683.         return -1;
  684.     avcC_len = 5 + 1 + 2 + p_mkv->sps_len + 1 + 2 + p_mkv->pps_len;
  685.     avcC = malloc(avcC_len);
  686.     if (avcC == NULL)
  687.         return -1;
  688.     avcC[0] = 1;
  689.     avcC[1] = p_mkv->sps[1];
  690.     avcC[2] = p_mkv->sps[2];
  691.     avcC[3] = p_mkv->sps[3];
  692.     avcC[4] = 0xff; // nalu size length is four bytes
  693.     avcC[5] = 0xe1; // one sps
  694.     avcC[6] = p_mkv->sps_len >> 8;
  695.     avcC[7] = p_mkv->sps_len;
  696.     memcpy(avcC+8, p_mkv->sps, p_mkv->sps_len);
  697.     avcC[8+p_mkv->sps_len] = 1; // one pps
  698.     avcC[9+p_mkv->sps_len] = p_mkv->pps_len >> 8;
  699.     avcC[10+p_mkv->sps_len] = p_mkv->pps_len;
  700.     memcpy( avcC+11+p_mkv->sps_len, p_mkv->pps, p_mkv->pps_len );
  701.     ret = mk_writeHeader( p_mkv->w, "x264", "V_MPEG4/ISO/AVC",
  702.                           avcC, avcC_len, p_mkv->frame_duration, 50000,
  703.                           p_mkv->width, p_mkv->height,
  704.                           p_mkv->d_width, p_mkv->d_height );
  705.     free( avcC );
  706.     p_mkv->b_header_written = 1;
  707.     return ret;
  708. }
  709. int open_file_mkv( char *psz_filename, hnd_t *p_handle )
  710. {
  711.     mkv_t *p_mkv;
  712.     *p_handle = NULL;
  713.     p_mkv  = malloc(sizeof(*p_mkv));
  714.     if (p_mkv == NULL)
  715.         return -1;
  716.     memset(p_mkv, 0, sizeof(*p_mkv));
  717.     p_mkv->w = mk_createWriter(psz_filename);
  718.     if (p_mkv->w == NULL)
  719.     {
  720.         free(p_mkv);
  721.         return -1;
  722.     }
  723.     *p_handle = p_mkv;
  724.     return 0;
  725. }
  726. int set_param_mkv( hnd_t handle, x264_param_t *p_param )
  727. {
  728.     mkv_t   *p_mkv = handle;
  729.     int64_t dw, dh;
  730.     if( p_param->i_fps_num > 0 )
  731.     {
  732.         p_mkv->frame_duration = (int64_t)p_param->i_fps_den *
  733.                                 (int64_t)1000000000 / p_param->i_fps_num;
  734.         p_mkv->fps_num = p_param->i_fps_num;
  735.     }
  736.     else
  737.     {
  738.         p_mkv->frame_duration = 0;
  739.         p_mkv->fps_num = 1;
  740.     }
  741.     p_mkv->width = p_param->i_width;
  742.     p_mkv->height = p_param->i_height;
  743.     if( p_param->vui.i_sar_width && p_param->vui.i_sar_height )
  744.     {
  745.         dw = (int64_t)p_param->i_width  * p_param->vui.i_sar_width;
  746.         dh = (int64_t)p_param->i_height * p_param->vui.i_sar_height;
  747.     }
  748.     else
  749.     {
  750.         dw = p_param->i_width;
  751.         dh = p_param->i_height;
  752.     }
  753.     if( dw > 0 && dh > 0 )
  754.     {
  755.         int64_t x = gcd( dw, dh );
  756.         dw /= x;
  757.         dh /= x;
  758.     }
  759.     p_mkv->d_width = (int)dw;
  760.     p_mkv->d_height = (int)dh;
  761.     return 0;
  762. }
  763. int write_nalu_mkv( hnd_t handle, uint8_t *p_nalu, int i_size )
  764. {
  765.     mkv_t *p_mkv = handle;
  766.     uint8_t type = p_nalu[4] & 0x1f;
  767.     uint8_t dsize[4];
  768.     int psize;
  769.     switch( type )
  770.     {
  771.     // sps
  772.     case 0x07:
  773.         if( !p_mkv->sps )
  774.         {
  775.             p_mkv->sps = malloc(i_size - 4);
  776.             if (p_mkv->sps == NULL)
  777.                 return -1;
  778.             p_mkv->sps_len = i_size - 4;
  779.             memcpy(p_mkv->sps, p_nalu + 4, i_size - 4);
  780.         }
  781.         break;
  782.     // pps
  783.     case 0x08:
  784.         if( !p_mkv->pps )
  785.         {
  786.             p_mkv->pps = malloc(i_size - 4);
  787.             if (p_mkv->pps == NULL)
  788.                 return -1;
  789.             p_mkv->pps_len = i_size - 4;
  790.             memcpy(p_mkv->pps, p_nalu + 4, i_size - 4);
  791.         }
  792.         break;
  793.     // slice, sei
  794.     case 0x1:
  795.     case 0x5:
  796.     case 0x6:
  797.         if( !p_mkv->b_writing_frame )
  798.         {
  799.             if( mk_startFrame(p_mkv->w) < 0 )
  800.                 return -1;
  801.             p_mkv->b_writing_frame = 1;
  802.         }
  803.         psize = i_size - 4 ;
  804.         dsize[0] = psize >> 24;
  805.         dsize[1] = psize >> 16;
  806.         dsize[2] = psize >> 8;
  807.         dsize[3] = psize;
  808.         if( mk_addFrameData(p_mkv->w, dsize, 4) < 0 ||
  809.             mk_addFrameData(p_mkv->w, p_nalu + 4, i_size - 4) < 0 )
  810.             return -1;
  811.         break;
  812.     default:
  813.         break;
  814.     }
  815.     if( !p_mkv->b_header_written && p_mkv->pps && p_mkv->sps &&
  816.         write_header_mkv(p_mkv) < 0 )
  817.         return -1;
  818.     return i_size;
  819. }
  820. int set_eop_mkv( hnd_t handle, x264_picture_t *p_picture )
  821. {
  822.     mkv_t *p_mkv = handle;
  823.     int64_t i_stamp = (int64_t)(p_picture->i_pts * 1e9 / p_mkv->fps_num);
  824.     p_mkv->b_writing_frame = 0;
  825.     return mk_setFrameFlags( p_mkv->w, i_stamp,
  826.                              p_picture->i_type == X264_TYPE_IDR );
  827. }
  828. int close_file_mkv( hnd_t handle )
  829. {
  830.     mkv_t *p_mkv = handle;
  831.     int   ret;
  832.     if( p_mkv->sps )
  833.         free( p_mkv->sps );
  834.     if( p_mkv->pps )
  835.         free( p_mkv->pps );
  836.     ret = mk_close(p_mkv->w);
  837.     free( p_mkv );
  838.     return ret;
  839. }