x264.c

来自「这个库实现了录象功能」· C语言 代码 · 共 933 行 · 第 1/2 页

C
933
字号
/******************************************************************************* x264.c libquicktime - A library for reading and writing quicktime/avi/mp4 files. http://libquicktime.sourceforge.net Copyright (C) 2002 Heroine Virtual Ltd. Copyright (C) 2002-2007 Members of the libquicktime project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************/ #include "lqt_private.h"#include <x264.h>#include <stdlib.h>#include <string.h>#include <quicktime/colormodels.h>#include "qtx264.h"#define LOG_DOMAIN "x264"// #define DUMP_CONFIG#ifdef DUMP_CONFIGstatic void dump_params(x264_param_t * params)  {  lqt_dump("X264 params:\n");  lqt_dump("  cpu:       %08x\n", params->cpu);  lqt_dump("  i_threads: %d\n", params->i_threads);  lqt_dump("  i_width: %d\n", params->i_width);  lqt_dump("  i_height: %d\n", params->i_height);  lqt_dump("  i_csp: %d\n", params->i_csp);  lqt_dump("  i_level_idc: %d\n", params->i_level_idc);  lqt_dump("  i_frame_total: %d\n", params->i_frame_total);  lqt_dump("  vui:\n");  lqt_dump("    i_sar_height: %d\n", params->vui.i_sar_height);  lqt_dump("    i_sar_width:  %d\n", params->vui.i_sar_width);  lqt_dump("    i_overscan:   %d\n", params->vui.i_overscan);  lqt_dump("    i_vidformat:  %d\n", params->vui.i_vidformat);  lqt_dump("    b_fullrange:  %d\n", params->vui.b_fullrange);  lqt_dump("    i_colorprim:  %d\n", params->vui.i_colorprim);  lqt_dump("    i_transfer:   %d\n", params->vui.i_transfer);  lqt_dump("    i_colmatrix:  %d\n", params->vui.i_colmatrix);  lqt_dump("    i_chroma_loc: %d\n", params->vui.i_chroma_loc);  lqt_dump("  fps: %d:%d\n", params->i_fps_num, params->i_fps_den);  /* Bitstream parameters */    lqt_dump("  i_frame_reference:           %d\n", params->i_frame_reference); // 1..16   lqt_dump("  i_keyint_min:                %d\n", params->i_keyint_min);        lqt_dump("  i_keyint_max:                %d\n", params->i_keyint_max);  lqt_dump("  i_scenecut_threshold:        %d\n", params->i_scenecut_threshold);   lqt_dump("  i_bframe:                    %d\n", params->i_bframe);          // 0.. X264_BFRAME_MAX  lqt_dump("  b_bframe_adaptive:           %d\n", params->b_bframe_adaptive);  lqt_dump("  i_bframe_bias:               %d\n", params->i_bframe_bias);  lqt_dump("  b_bframe_pyramid:            %d\n", params->b_bframe_pyramid);    lqt_dump("  b_deblocking_filter:         %d\n", params->b_deblocking_filter);  lqt_dump("  i_deblocking_filter_alphac0: %d\n", params->i_deblocking_filter_alphac0); // -6..6  lqt_dump("  i_deblocking_filter_beta:    %d\n", params->i_deblocking_filter_beta);    // -6..6  lqt_dump("  b_cabac:                     %d\n", params->b_cabac);  lqt_dump("  i_cabac_init_idc:            %d\n", params->i_cabac_init_idc); // 0..2  lqt_dump("  i_cqm_preset:                %d\n", params->i_cqm_preset);    lqt_dump("  psz_cqm_file:                %s\n", params->psz_cqm_file);  lqt_dump("  Analyze:\n");  // ORED value of X264_ANALYSE_I4x4, X264_ANALYSE_I8x8, X264_ANALYSE_PSUB16x16, X264_ANALYSE_PSUB8x8,  // X264_ANALYSE_BSUB16x16    lqt_dump("    intra:              %d\n", params->analyse.intra);  lqt_dump("    inter:              %d\n", params->analyse.inter);      lqt_dump("    b_transform_8x8:    %d\n", params->analyse.b_transform_8x8);  lqt_dump("    b_weighted_bipred:  %d\n", params->analyse.b_weighted_bipred);  lqt_dump("    i_direct_mv_pred:   %d\n", params->analyse.i_direct_mv_pred);  lqt_dump("    i_chroma_qp_offset: %d\n", params->analyse.i_chroma_qp_offset);  // X264_ME_DIA, X264_ME_HEX, X264_ME_UMH, X264_ME_ESA  lqt_dump("    i_me_method:        %d\n", params->analyse.i_me_method);     lqt_dump("    i_me_range:         %d\n", params->analyse.i_me_range);  lqt_dump("    i_mv_range:         %d\n", params->analyse.i_mv_range);  lqt_dump("    i_subpel_refine:    %d\n", params->analyse.i_subpel_refine); // 1..7  lqt_dump("    b_bidir_me:         %d\n", params->analyse.b_bidir_me);  lqt_dump("    b_chroma_me:        %d\n", params->analyse.b_chroma_me);  lqt_dump("    b_bframe_rdo:       %d\n", params->analyse.b_bframe_rdo);  lqt_dump("    b_mixed_references: %d\n", params->analyse.b_mixed_references);  lqt_dump("    i_trellis:          %d\n", params->analyse.i_trellis);         // 0..2  lqt_dump("    b_fast_pskip:       %d\n", params->analyse.b_fast_pskip);  lqt_dump("    i_noise_reduction:  %d\n", params->analyse.i_noise_reduction); // 0..1<<16  lqt_dump("    b_psnr:             %d\n", params->analyse.b_psnr);  lqt_dump("  Rate control:\n");  lqt_dump("    i_rc_method:        %d\n", params->rc.i_rc_method);  lqt_dump("    i_qp_constant:      %d\n", params->rc.i_qp_constant);  lqt_dump("    i_qp_min:           %d\n", params->rc.i_qp_min);  lqt_dump("    i_qp_max:           %d\n", params->rc.i_qp_max);  lqt_dump("    i_qp_step:          %d\n", params->rc.i_qp_step);  lqt_dump("    i_bitrate:          %d\n", params->rc.i_bitrate);#if X264_BUILD < 54  lqt_dump("    i_rf_constant:      %d\n", params->rc.i_rf_constant);#else  lqt_dump("    f_rf_constant:      %f\n", params->rc.f_rf_constant);#endif  lqt_dump("    f_rate_tolerance:   %f\n", params->rc.f_rate_tolerance);  lqt_dump("    i_vbv_max_bitrate:  %d\n", params->rc.i_vbv_max_bitrate);  lqt_dump("    i_vbv_buffer_size:  %d\n", params->rc.i_vbv_buffer_size);  lqt_dump("    f_vbv_buffer_init:  %f\n", params->rc.f_vbv_buffer_init);  lqt_dump("    f_ip_factor:        %f\n", params->rc.f_ip_factor);  lqt_dump("    f_pb_factor:        %f\n", params->rc.f_pb_factor);    }#endif // DUMP_CONFIG/* *  x264 encoder. *  NAL reformatting stuff taken from ffmpeg/libavformat/movenc.c */ typedef struct  {  x264_param_t params;  x264_t *enc;  x264_picture_t pic;   int initialized;  /* For raw x264 output */  uint8_t * work_buffer;  int work_buffer_size;  /* Reformatted buffer */  uint8_t * work_buffer_1;  int work_buffer_alloc_1;  int total_passes;  int pass;  char * stats_filename;    } quicktime_x264_codec_t;static int delete_codec(quicktime_video_map_t *vtrack)  {  quicktime_x264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;  if(codec->enc)    x264_encoder_close(codec->enc);  if(codec->stats_filename)    free(codec->stats_filename);  free(codec);  return 0;  }static intencode_nals(uint8_t *buf, int size, x264_nal_t *nals, int nnal)  {  uint8_t *p = buf;  int i;  int s;    for(i = 0; i < nnal; i++)    {    s = x264_nal_encode(p, &size, 1, nals + i);    if(s < 0)      return -1;    p += s;    }    return p - buf;  }static uint8_t *avc_find_startcode( uint8_t *p, uint8_t *end )  {  uint8_t *a = p + 4 - ((long)p & 3);    for( end -= 3; p < a && p < end; p++ )    {    if( p[0] == 0 && p[1] == 0 && p[2] == 1 )      return p;    }    for( end -= 3; p < end; p += 4 )    {    uint32_t x = *(uint32_t*)p;    //      if( (x - 0x01000100) & (~x) & 0x80008000 ) // little endian    //      if( (x - 0x00010001) & (~x) & 0x00800080 ) // big endian    if( (x - 0x01010101) & (~x) & 0x80808080 )      { // generic      if( p[1] == 0 )        {        if( p[0] == 0 && p[2] == 1 )          return p;        if( p[2] == 0 && p[3] == 1 )          return p+1;        }      if( p[3] == 0 )        {        if( p[2] == 0 && p[4] == 1 )          return p+2;        if( p[4] == 0 && p[5] == 1 )          return p+3;        }      }    }    for( end += 3; p < end; p++ )    {    if( p[0] == 0 && p[1] == 0 && p[2] == 1 )      return p;    }  return end + 3;  }static int avc_parse_nal_units(uint8_t *src, int src_size,                               uint8_t ** _dst, int * dst_alloc)  {  uint8_t *p = src;  uint8_t *end = p + src_size;  uint8_t *nal_start, *nal_end;  uint8_t * dst, * ret_ptr;  int ret_size = 0;  uint32_t nal_size;  dst = *_dst;    /* Get the size */  nal_start = avc_find_startcode(p, end);  while (nal_start < end)    {    while(!*(nal_start++));    nal_end = avc_find_startcode(nal_start, end);    ret_size += 4 + (int)(nal_end - nal_start);    nal_start = nal_end;    }  if(ret_size > *dst_alloc)    {    *dst_alloc = ret_size + 1024;    dst = realloc(dst, *dst_alloc);    }    /* Copy */  ret_ptr = dst;    nal_start = avc_find_startcode(p, end);  while (nal_start < end)    {    while(!*(nal_start++));    nal_end = avc_find_startcode(nal_start, end);    nal_size = nal_end - nal_start;    ret_ptr[0] = (nal_size >> 24) & 0xff;    ret_ptr[1] = (nal_size >> 16) & 0xff;    ret_ptr[2] = (nal_size >> 8) & 0xff;    ret_ptr[3] = (nal_size) & 0xff;    ret_ptr += 4;    memcpy(ret_ptr, nal_start, nal_size);    ret_ptr += nal_size;        nal_start = nal_end;    }    *_dst = dst;  return ret_size;  }static uint8_t * create_avcc_atom(quicktime_x264_codec_t * codec,                                  int * ret_size)  {  int i;  x264_nal_t *nal;  int nnal;  uint8_t * ret, *ret_ptr;  uint8_t * tmp_buf, *tmp_buf_1 = (uint8_t*)0;  int tmp_buf_alloc_1 = 0;  int tmp_size;  int tmp_size_1;    uint8_t * ptr, *ptr_end;  uint32_t nal_size;  uint32_t sps_size=0, pps_size=0;  uint8_t *sps=0, *pps=0;  uint8_t nal_type;    x264_encoder_headers(codec->enc, &nal, &nnal);  tmp_size = 0;  /* 5 bytes NAL header + worst case escaping */  for(i = 0; i < nnal; i++)    tmp_size += 5 + nal[i].i_payload * 4 / 3;  tmp_buf = malloc(tmp_size);  tmp_size = encode_nals(tmp_buf, tmp_size, nal, nnal);    tmp_size_1 = avc_parse_nal_units(tmp_buf, tmp_size,                                   &tmp_buf_1, &tmp_buf_alloc_1);  /* Look for sps and pps */  ptr = tmp_buf_1;  ptr_end = tmp_buf_1 + tmp_size_1;  /* look for sps and pps */  while(ptr < ptr_end)    {    nal_size =      ((uint32_t)ptr[0] << 24) |      ((uint32_t)ptr[1] << 16) |      ((uint32_t)ptr[2] << 8) |      (uint32_t)ptr[3];        nal_type = ptr[4] & 0x1f;    if (nal_type == 7)      { /* SPS */      sps = ptr + 4;      sps_size = nal_size;      }    else if (nal_type == 8)      { /* PPS */      pps = ptr + 4;      pps_size = nal_size;      }    ptr += nal_size + 4;    }  *ret_size =    6 +        // Initial bytes    2 +        // sps_size    sps_size + // sps    1 +        // num_pps    2 +        // pps_size    pps_size;  // pps    ret = malloc(*ret_size);  ret_ptr = ret;    /* Start encoding */  *(ret_ptr++) = 0x01; /* Version */  *(ret_ptr++) = 0x4d; /* 77, profile */  *(ret_ptr++) = 0x40; /* 64, profile compat */  *(ret_ptr++) = 0x1E; /* 30, level (31?) */  *(ret_ptr++) = 0xFF; /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */  *(ret_ptr++) = 0xE1; /* 3 bits reserved (111) + 5 bits number of sps (00001)       */  /* sps_size */  ret_ptr[0] = (sps_size >> 8) & 0xff;  ret_ptr[1] = sps_size & 0xff;  ret_ptr += 2;  /* sps */  memcpy(ret_ptr, sps, sps_size);  ret_ptr += sps_size;  /* num_pps */  *(ret_ptr++) = 0x01;  /* pps_size */  ret_ptr[0] = (pps_size >> 8) & 0xff;  ret_ptr[1] = pps_size & 0xff;  ret_ptr += 2;  /* pps */  memcpy(ret_ptr, pps, pps_size);  ret_ptr += pps_size;  free(tmp_buf);  free(tmp_buf_1);    return ret;  }static int flush_frame(quicktime_t *file, int track,                       x264_picture_t * pic_in)  {  int result;  quicktime_atom_t chunk_atom;  x264_nal_t *nal;  int nnal;  x264_picture_t pic_out;  int encoded_size;  quicktime_video_map_t *vtrack = &(file->vtracks[track]);  quicktime_x264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;  quicktime_trak_t *trak = vtrack->track;  pic_out.i_pts = 0;  /* Encode frames, get nals */  if(x264_encoder_encode(codec->enc, &nal, &nnal, pic_in, &pic_out))    return 0;    /* Encode nals -> get h264 stream */  encoded_size = encode_nals(codec->work_buffer,                             codec->work_buffer_size, nal, nnal);    /* Reformat nals */  encoded_size = avc_parse_nal_units(codec->work_buffer,                                     encoded_size,                                     &codec->work_buffer_1,                                     &codec->work_buffer_alloc_1);  if(encoded_size < 0)    return 0;  vtrack->coded_timestamp =   pic_out.i_pts;  if(encoded_size)    {    quicktime_write_chunk_header(file, trak, &chunk_atom);      result = !quicktime_write_data(file,                                    codec->work_buffer_1,                                    encoded_size);    quicktime_write_chunk_footer(file,                                  trak,                                  vtrack->current_chunk,                                 &chunk_atom,                                  1);      if(pic_out.i_type == X264_TYPE_IDR)      quicktime_insert_keyframe(file, vtrack->current_chunk-1, track);    vtrack->current_chunk++;    return 1;    }  return 0;  }static int set_pass_x264(quicktime_t *file,                            int track, int pass, int total_passes,                           const char * stats_file)  {  quicktime_video_map_t *vtrack = &(file->vtracks[track]);  quicktime_x264_codec_t *codec =    ((quicktime_codec_t*)vtrack->codec)->priv;  codec->total_passes = total_passes;  codec->pass = pass;  codec->stats_filename = malloc(strlen(stats_file)+1);  strcpy(codec->stats_filename, stats_file);    return 1;  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?