⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 muxers.c

📁 linux下编译已经通过
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * muxers.c: h264 file i/o plugins ***************************************************************************** * Copyright (C) 2003-2006 x264 project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************/#include "common/common.h"#include "x264.h"#include "matroska.h"#include "muxers.h"#ifndef _MSC_VER#include "config.h"#endif#include <sys/types.h>#ifdef AVIS_INPUT#include <windows.h>#include <vfw.h>#endif#ifdef MP4_OUTPUT#include <gpac/isomedia.h>#endifstatic int64_t gcd( int64_t a, int64_t b ){    while (1)    {        int64_t c = a % b;        if( !c )            return b;        a = b;        b = c;    }}typedef struct {    FILE *fh;    int width, height;    int next_frame;} yuv_input_t;/* raw 420 yuv file operation */int open_file_yuv( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ){    yuv_input_t *h = malloc(sizeof(yuv_input_t));    h->width = p_param->i_width;    h->height = p_param->i_height;    h->next_frame = 0;    if( !strcmp(psz_filename, "-") )        h->fh = stdin;    else        h->fh = fopen(psz_filename, "rb");    if( h->fh == NULL )        return -1;    *p_handle = (hnd_t)h;    return 0;}int get_frame_total_yuv( hnd_t handle ){    yuv_input_t *h = handle;    int i_frame_total = 0;    if( !fseek( h->fh, 0, SEEK_END ) )    {        uint64_t i_size = ftell( h->fh );        fseek( h->fh, 0, SEEK_SET );        i_frame_total = (int)(i_size / ( h->width * h->height * 3 / 2 ));    }    return i_frame_total;}int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame ){    yuv_input_t *h = handle;    if( i_frame != h->next_frame )        if( fseek( h->fh, (uint64_t)i_frame * h->width * h->height * 3 / 2, SEEK_SET ) )            return -1;    if( fread( p_pic->img.plane[0], 1, h->width * h->height, h->fh ) <= 0            || fread( p_pic->img.plane[1], 1, h->width * h->height / 4, h->fh ) <= 0            || fread( p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh ) <= 0 )        return -1;    h->next_frame = i_frame+1;    return 0;}int close_file_yuv(hnd_t handle){    yuv_input_t *h = handle;    if( !h || !h->fh )        return 0;    fclose( h->fh );    free( h );    return 0;}/* YUV4MPEG2 raw 420 yuv file operation */typedef struct {    FILE *fh;    int width, height;    int next_frame;    int seq_header_len, frame_header_len;    int frame_size;} y4m_input_t;#define Y4M_MAGIC "YUV4MPEG2"#define MAX_YUV4_HEADER 80#define Y4M_FRAME_MAGIC "FRAME"#define MAX_FRAME_HEADER 80int open_file_y4m( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ){    int  i, n, d;    int  interlaced;    char header[MAX_YUV4_HEADER+10];    char *tokstart, *tokend, *header_end;    y4m_input_t *h = malloc(sizeof(y4m_input_t));    h->next_frame = 0;    if( !strcmp(psz_filename, "-") )        h->fh = stdin;    else        h->fh = fopen(psz_filename, "rb");    if( h->fh == NULL )        return -1;    h->frame_header_len = strlen(Y4M_FRAME_MAGIC)+1;    /* Read header */    for( i=0; i<MAX_YUV4_HEADER; i++ )    {        header[i] = fgetc(h->fh);        if( header[i] == '\n' )        {            /* Add a space after last option. Makes parsing "444" vs               "444alpha" easier. */            header[i+1] = 0x20;            header[i+2] = 0;            break;        }    }    if( i == MAX_YUV4_HEADER || strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC)) )        return -1;    /* Scan properties */    header_end = &header[i+1]; /* Include space */    h->seq_header_len = i+1;    for( tokstart = &header[strlen(Y4M_MAGIC)+1]; tokstart < header_end; tokstart++ )    {        if(*tokstart==0x20) continue;        switch(*tokstart++)        {        case 'W': /* Width. Required. */            h->width = p_param->i_width = strtol(tokstart, &tokend, 10);            tokstart=tokend;            break;        case 'H': /* Height. Required. */            h->height = p_param->i_height = strtol(tokstart, &tokend, 10);            tokstart=tokend;            break;        case 'C': /* Color space */            if( strncmp("420", tokstart, 3) )            {                fprintf(stderr, "Colorspace unhandled\n");                return -1;            }            tokstart = strchr(tokstart, 0x20);            break;        case 'I': /* Interlace type */            switch(*tokstart++)            {            case 'p': interlaced = 0; break;            case '?':            case 't':            case 'b':            case 'm':            default: interlaced = 1;                fprintf(stderr, "Warning, this sequence might be interlaced\n");            }            break;        case 'F': /* Frame rate - 0:0 if unknown */            if( sscanf(tokstart, "%d:%d", &n, &d) == 2 && n && d )            {                x264_reduce_fraction( &n, &d );                p_param->i_fps_num = n;                p_param->i_fps_den = d;            }            tokstart = strchr(tokstart, 0x20);            break;        case 'A': /* Pixel aspect - 0:0 if unknown */            if( sscanf(tokstart, "%d:%d", &n, &d) == 2 && n && d )            {                x264_reduce_fraction( &n, &d );                p_param->vui.i_sar_width = n;                p_param->vui.i_sar_height = d;            }            tokstart = strchr(tokstart, 0x20);            break;        case 'X': /* Vendor extensions */            if( !strncmp("YSCSS=",tokstart,6) )            {                /* Older nonstandard pixel format representation */                tokstart += 6;                if( strncmp("420JPEG",tokstart,7) &&                    strncmp("420MPEG2",tokstart,8) &&                    strncmp("420PALDV",tokstart,8) )                {                    fprintf(stderr, "Unsupported extended colorspace\n");                    return -1;                }            }            tokstart = strchr(tokstart, 0x20);            break;        }    }    fprintf(stderr, "yuv4mpeg: %ix%i@%i/%ifps, %i:%i\n",            h->width, h->height, p_param->i_fps_num, p_param->i_fps_den,            p_param->vui.i_sar_width, p_param->vui.i_sar_height);    *p_handle = (hnd_t)h;    return 0;}/* Most common case: frame_header = "FRAME" */int get_frame_total_y4m( hnd_t handle ){    y4m_input_t *h             = handle;    int          i_frame_total = 0;    uint64_t     init_pos      = ftell(h->fh);    if( !fseek( h->fh, 0, SEEK_END ) )    {        uint64_t i_size = ftell( h->fh );        fseek( h->fh, init_pos, SEEK_SET );        i_frame_total = (int)((i_size - h->seq_header_len) /                              (3*(h->width*h->height)/2+h->frame_header_len));    }    return i_frame_total;}int read_frame_y4m( x264_picture_t *p_pic, hnd_t handle, int i_frame ){    int          slen = strlen(Y4M_FRAME_MAGIC);    int          i    = 0;    char         header[16];    y4m_input_t *h    = handle;    if( i_frame != h->next_frame )    {        if (fseek(h->fh, (uint64_t)i_frame*(3*(h->width*h->height)/2+h->frame_header_len)                  + h->seq_header_len, SEEK_SET))            return -1;    }    /* Read frame header - without terminating '\n' */    if (fread(header, 1, slen, h->fh) != slen)        return -1;        header[slen] = 0;    if (strncmp(header, Y4M_FRAME_MAGIC, slen))    {        fprintf(stderr, "Bad header magic (%08X <=> %s)\n",                *((uint32_t*)header), header);        return -1;    }      /* Skip most of it */    while (i<MAX_FRAME_HEADER && fgetc(h->fh) != '\n')        i++;    if (i == MAX_FRAME_HEADER)    {        fprintf(stderr, "Bad frame header!\n");        return -1;    }    h->frame_header_len = i+slen+1;    if( fread(p_pic->img.plane[0], 1, h->width*h->height, h->fh) <= 0        || fread(p_pic->img.plane[1], 1, h->width * h->height / 4, h->fh) <= 0        || fread(p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh) <= 0)        return -1;    h->next_frame = i_frame+1;    return 0;}int close_file_y4m(hnd_t handle){    y4m_input_t *h = handle;    if( !h || !h->fh )        return 0;    fclose( h->fh );    free( h );    return 0;}/* avs/avi input file support under cygwin */#ifdef AVIS_INPUTtypedef struct {    PAVISTREAM p_avi;    int width, height;} avis_input_t;int open_file_avis( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ){    avis_input_t *h = malloc(sizeof(avis_input_t));    AVISTREAMINFO info;    int i;    *p_handle = (hnd_t)h;    AVIFileInit();    if( AVIStreamOpenFromFile( &h->p_avi, psz_filename, streamtypeVIDEO, 0, OF_READ, NULL ) )    {        AVIFileExit();        return -1;    }    if( AVIStreamInfo(h->p_avi, &info, sizeof(AVISTREAMINFO)) )    {        AVIStreamRelease(h->p_avi);        AVIFileExit();        return -1;    }    // check input format    if (info.fccHandler != MAKEFOURCC('Y', 'V', '1', '2'))    {        fprintf( stderr, "avis [error]: unsupported input format (%c%c%c%c)\n",            (char)(info.fccHandler & 0xff), (char)((info.fccHandler >> 8) & 0xff),            (char)((info.fccHandler >> 16) & 0xff), (char)((info.fccHandler >> 24)) );        AVIStreamRelease(h->p_avi);        AVIFileExit();        return -1;    }    h->width =    p_param->i_width = info.rcFrame.right - info.rcFrame.left;    h->height =    p_param->i_height = info.rcFrame.bottom - info.rcFrame.top;    i = gcd(info.dwRate, info.dwScale);    p_param->i_fps_den = info.dwScale / i;    p_param->i_fps_num = info.dwRate / i;    fprintf( stderr, "avis [info]: %dx%d @ %.2f fps (%d frames)\n",        p_param->i_width, p_param->i_height,        (double)p_param->i_fps_num / (double)p_param->i_fps_den,        (int)info.dwLength );    return 0;}int get_frame_total_avis( hnd_t handle ){    avis_input_t *h = handle;    AVISTREAMINFO info;    if( AVIStreamInfo(h->p_avi, &info, sizeof(AVISTREAMINFO)) )        return -1;    return info.dwLength;}int read_frame_avis( x264_picture_t *p_pic, hnd_t handle, int i_frame ){    avis_input_t *h = handle;    p_pic->img.i_csp = X264_CSP_YV12;    if( AVIStreamRead(h->p_avi, i_frame, 1, p_pic->img.plane[0], h->width * h->height * 3 / 2, NULL, NULL ) )        return -1;    return 0;}int close_file_avis( hnd_t handle ){    avis_input_t *h = handle;    AVIStreamRelease(h->p_avi);    AVIFileExit();    free(h);    return 0;}#endif#ifdef HAVE_PTHREADtypedef struct {    int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame );    int (*p_close_infile)( hnd_t handle );    hnd_t p_handle;    x264_picture_t pic;    x264_pthread_t tid;    int next_frame;    int frame_total;    struct thread_input_arg_t *next_args;} thread_input_t;typedef struct thread_input_arg_t {    thread_input_t *h;    x264_picture_t *pic;    int i_frame;    int status;} thread_input_arg_t;int open_file_thread( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ){    thread_input_t *h = malloc(sizeof(thread_input_t));    x264_picture_alloc( &h->pic, X264_CSP_I420, p_param->i_width, p_param->i_height );    h->p_read_frame = p_read_frame;    h->p_close_infile = p_close_infile;    h->p_handle = *p_handle;    h->next_frame = -1;    h->next_args = malloc(sizeof(thread_input_arg_t));    h->next_args->h = h;    h->next_args->status = 0;    h->frame_total = p_get_frame_total( h->p_handle );    *p_handle = (hnd_t)h;    return 0;}int get_frame_total_thread( hnd_t handle ){    thread_input_t *h = handle;    return h->frame_total;}void read_frame_thread_int( thread_input_arg_t *i ){    i->status = i->h->p_read_frame( i->pic, i->h->p_handle, i->i_frame );}int read_frame_thread( x264_picture_t *p_pic, hnd_t handle, int i_frame ){    thread_input_t *h = handle;    UNUSED void *stuff;    int ret = 0;    if( h->next_frame >= 0 )    {        x264_pthread_join( h->tid, &stuff );        ret |= h->next_args->status;    }    if( h->next_frame == i_frame )    {        XCHG( x264_picture_t, *p_pic, h->pic );    }    else    {        ret |= h->p_read_frame( p_pic, h->p_handle, i_frame );    }    if( !h->frame_total || i_frame+1 < h->frame_total )    {        h->next_frame =        h->next_args->i_frame = i_frame+1;        h->next_args->pic = &h->pic;        x264_pthread_create( &h->tid, NULL, (void*)read_frame_thread_int, h->next_args );    }    else        h->next_frame = -1;    return ret;}int close_file_thread( hnd_t handle ){

⌨️ 快捷键说明

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