且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

x264编码得到的文件,在文件头部的一些东西,有了新发现

更新时间:2022-09-01 18:18:26

在x264.dsw工程中,找了一下,找到点相关的东西。
另外,x264.exe在编码文件时,只有一个地方进行文件的写入,就是
int write_nalu_bsf( hnd_t handle, uint8_t *p_nalu, int i_size )
{
   if (fwrite(p_nalu, i_size, 1, (FILE *)handle) > 0)
{
         return i_size;
}
    return -1;
}
如果把函数里的代码注释掉,会发现,虽然在不停的编码,但最终文件大小始终为0,从这一点可以证明只有此处进行文件的写入操作。

那么,序列参数集是哪里来的呢,又找到一部分东西,在encoder.c文件的函数:
int     x264_encoder_encode( x264_t *h,/* 指定编码器 */
                             x264_nal_t **pp_nal, /* x264_nal_t * */
 int *pi_nal, /* int */
                             x264_picture_t *pic_in,
                             x264_picture_t *pic_out )
中,有如下代码:

    /* Write SPS and PPS 写序列参数集、图像参数集以及SEI版本信息,并不是写入文件,而是写入输出缓冲区 最后通过p_write_nalu中的fwrite写入到文件*/
    if( i_nal_type == NAL_SLICE_IDR && h->param.b_repeat_headers )
    {
printf("encoder.c : Write SPS and PPS");
system("pause");//暂停,任意键继续

        if( h->fenc->i_frame == 0 )
        {
            /* identify ourself */
            x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
            x264_sei_version_write( h, &h->out.bs );
            x264_nal_end( h );
        }

        /* generate sequence parameters */
        x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
        x264_sps_write( &h->out.bs, h->sps );
        x264_nal_end( h );

        /* generate picture parameters */
        x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
        x264_pps_write( &h->out.bs, h->pps );
        x264_nal_end( h );
    }

    /* Write frame 写入帧,并不是写入文件,而是写入输出缓冲区*/
    i_frame_size = x264_slices_write( h );

在图一中,看到有一个网址http://www.videolan.org,在源码中搜索这个网址,找到唯一的一处,也就是如下的函数:
void x264_sei_version_write( x264_t *h, bs_t *s )
{
    int i;
    // random ID number generated according to ISO-11578
    const uint8_t uuid[16] = {
        0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7,
        0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef
    };
    char version[1200];
    int length;
    char *opts = x264_param2string( &h->param, 0 );

    sprintf( version, "x264 - core %d%s - H.264/MPEG-4 AVC codec - "
             "Copyleft 2005 - http://www.videolan.org/x264.html - options: %s",
             X264_BUILD, X264_VERSION, opts );
    x264_free( opts );
    length = strlen(version)+1+16;

    bs_write( s, 8, 0x5 ); // payload_type = user_data_unregistered
    // payload_size
    for( i = 0; i <= length-255; i += 255 )
        bs_write( s, 8, 255 );
    bs_write( s, 8, length-i );

    for( i = 0; i < 16; i++ )
        bs_write( s, 8, uuid[i] );
    for( i = 0; i < length-16; i++ )
        bs_write( s, 8, version[i] );

    bs_rbsp_trailing( s );
}
猜想:
如果是实时的话,可以模仿下面的这两句代码发送序列参数集和图像参数集:
x264_sps_write( &h->out.bs, h->sps );
x264_pps_write( &h->out.bs, h->pps );

实际就是要发送h->sps和h->pps

因为我编码的文件是可以播放的,所以实际已经产生了sps和pps,直接发送就行了。