Skip to content
Snippets Groups Projects
ffmpeg.c 81.3 KiB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
/*
 * FFmpeg main 
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
 *
 * 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 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
 *
 * This library is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
 * 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.
Fabrice Bellard's avatar
Fabrice Bellard committed
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Fabrice Bellard's avatar
Fabrice Bellard committed
 */
#define HAVE_AV_CONFIG_H
#include "avformat.h"

Fabrice Bellard's avatar
Fabrice Bellard committed
#ifndef CONFIG_WIN32
Fabrice Bellard's avatar
Fabrice Bellard committed
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <termios.h>
Fabrice Bellard's avatar
Fabrice Bellard committed
#include <sys/resource.h>
Fabrice Bellard's avatar
Fabrice Bellard committed
#endif
#ifdef __BEOS__
/* for snooze() */
#include <OS.h>
#endif
#include <time.h>
#include <ctype.h>
Fabrice Bellard's avatar
Fabrice Bellard committed


Fabrice Bellard's avatar
Fabrice Bellard committed
#define MAXINT64 INT64_C(0x7fffffffffffffff)

Fabrice Bellard's avatar
Fabrice Bellard committed
typedef struct {
    const char *name;
    int flags;
#define HAS_ARG    0x0001
#define OPT_BOOL   0x0002
#define OPT_EXPERT 0x0004
#define OPT_STRING 0x0008
    union {
        void (*func_arg)();
        int *int_arg;
        char **str_arg;
    } u;
    const char *help;
    const char *argname;
} OptionDef;

/* select an input stream for an output stream */
typedef struct AVStreamMap {
    int file_index;
    int stream_index;
} AVStreamMap;

extern const OptionDef options[];

void show_help(void);

#define MAX_FILES 20

static AVFormatContext *input_files[MAX_FILES];
static int nb_input_files = 0;

static AVFormatContext *output_files[MAX_FILES];
static int nb_output_files = 0;

static AVStreamMap stream_maps[MAX_FILES];
static int nb_stream_maps;

static AVInputFormat *file_iformat;
static AVOutputFormat *file_oformat;
Fabrice Bellard's avatar
Fabrice Bellard committed
static int frame_width  = 160;
static int frame_height = 128;
static int frame_topBand  = 0;
static int frame_bottomBand = 0;
static int frame_leftBand  = 0;
static int frame_rightBand = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
static int frame_rate = 25 * FRAME_RATE_BASE;
static int video_bit_rate = 200*1000;
static int video_bit_rate_tolerance = 4000*1000;
Fabrice Bellard's avatar
Fabrice Bellard committed
static int video_qscale = 0;
static int video_qmin = 2;
static int video_qmax = 31;
static int video_qdiff = 3;
static float video_qblur = 0.5;
static float video_qcomp = 0.5;
#if 0 //experimental, (can be removed)
static float video_rc_qsquish=1.0;
static float video_rc_qmod_amp=0;
static int video_rc_qmod_freq=0;
static char *video_rc_override_string=NULL;
static char *video_rc_eq="tex^qComp";
static int video_rc_buffer_size=0;
static float video_rc_buffer_aggressivity=1.0;
static int video_rc_max_rate=0;
static int video_rc_min_rate=0;
static float video_rc_initial_cplx=0;
static float video_b_qfactor = 1.25;
static float video_b_qoffset = 1.25;
static float video_i_qoffset = 0.0;
static int me_method = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
static int video_disable = 0;
static int video_codec_id = CODEC_ID_NONE;
static int same_quality = 0;
static int b_frames = 0;
static int use_4mv = 0;
static int do_deinterlace = 0;
static int workaround_bugs = FF_BUG_AUTODETECT;
static int error_resilience = 2;
static int error_concealment = 3;
static int dct_algo = 0;
static int use_part = 0;
static int packet_size = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed

static int gop_size = 12;
static int intra_only = 0;
static int audio_sample_rate = 44100;
static int audio_bit_rate = 64000;
static int audio_disable = 0;
static int audio_channels = 1;
static int audio_codec_id = CODEC_ID_NONE;

static INT64 recording_time = 0;
static int file_overwrite = 0;
static char *str_title = NULL;
static char *str_author = NULL;
static char *str_copyright = NULL;
static char *str_comment = NULL;
Fabrice Bellard's avatar
Fabrice Bellard committed
static int do_benchmark = 0;
static int do_hex_dump = 0;
static int do_vstats = 0;
static int do_pass = 0;
static char *pass_logfilename = NULL;
static int audio_stream_copy = 0;
static int video_stream_copy = 0;

#define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass"
Fabrice Bellard's avatar
Fabrice Bellard committed

#ifndef CONFIG_AUDIO_OSS
const char *audio_device = "none";
#endif
#ifndef CONFIG_VIDEO4LINUX
const char *v4l_device = "none";
#endif

Fabrice Bellard's avatar
Fabrice Bellard committed
typedef struct AVOutputStream {
    int file_index;          /* file index */
    int index;               /* stream index in the output file */
    int source_index;        /* AVInputStream index */
    AVStream *st;            /* stream in the output file */
    int encoding_needed;     /* true if encoding needed for this stream */
    int frame_number;
    /* input pts and corresponding output pts
       for A/V sync */
    double sync_ipts;
    INT64 sync_opts;
Fabrice Bellard's avatar
Fabrice Bellard committed
    /* video only */
    AVPicture pict_tmp;         /* temporary image for resizing */
    int video_resample;
    ImgReSampleContext *img_resample_ctx; /* for image resampling */
    
    /* audio only */
    int audio_resample;
    ReSampleContext *resample; /* for audio resampling */
    FifoBuffer fifo;     /* for compression: one audio fifo per codec */
Fabrice Bellard's avatar
Fabrice Bellard committed
} AVOutputStream;

typedef struct AVInputStream {
    int file_index;
    int index;
    AVStream *st;
    int discard;             /* true if stream data should be discarded */
    int decoding_needed;     /* true if the packets must be decoded in 'raw_fifo' */
    INT64 sample_index;      /* current sample */
    int frame_decoded;       /* true if a video or audio frame has been decoded */
Fabrice Bellard's avatar
Fabrice Bellard committed
} AVInputStream;

typedef struct AVInputFile {
    int eof_reached;      /* true if eof reached */
    int ist_index;        /* index of first stream in ist_table */
    int buffer_size;      /* current total buffer size */
    int buffer_size_max;  /* buffer size at which we consider we can stop
                             buffering */
    int nb_streams;       /* nb streams we are aware of */
Fabrice Bellard's avatar
Fabrice Bellard committed
} AVInputFile;

Fabrice Bellard's avatar
Fabrice Bellard committed
#ifndef CONFIG_WIN32

Fabrice Bellard's avatar
Fabrice Bellard committed
/* init terminal so that we can grab keys */
static struct termios oldtty;

static void term_exit(void)
{
    tcsetattr (0, TCSANOW, &oldtty);
}

static void term_init(void)
{
    struct termios tty;

    tcgetattr (0, &tty);
    oldtty = tty;

    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
                          |INLCR|IGNCR|ICRNL|IXON);
    tty.c_oflag |= OPOST;
    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
    tty.c_cflag &= ~(CSIZE|PARENB);
    tty.c_cflag |= CS8;
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 0;
    
    tcsetattr (0, TCSANOW, &tty);

    atexit(term_exit);
}

/* read a key without blocking */
static int read_key(void)
{
    struct timeval tv;
    int n;
    unsigned char ch;
    fd_set rfds;

    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    n = select(1, &rfds, NULL, NULL, &tv);
    if (n > 0) {
Fabrice Bellard's avatar
Fabrice Bellard committed
            return ch;
Fabrice Bellard's avatar
Fabrice Bellard committed
    }
    return -1;
}

Fabrice Bellard's avatar
Fabrice Bellard committed

/* no interactive support */
static void term_exit(void)
Fabrice Bellard's avatar
Fabrice Bellard committed
{
Fabrice Bellard's avatar
Fabrice Bellard committed

Fabrice Bellard's avatar
Fabrice Bellard committed

Fabrice Bellard's avatar
Fabrice Bellard committed
}

Fabrice Bellard's avatar
Fabrice Bellard committed

Fabrice Bellard's avatar
Fabrice Bellard committed
int read_ffserver_streams(AVFormatContext *s, const char *filename)
{
Fabrice Bellard's avatar
Fabrice Bellard committed
    AVFormatContext *ic;

    err = av_open_input_file(&ic, filename, NULL, FFM_PACKET_SIZE, NULL);
    if (err < 0)
        return err;
Fabrice Bellard's avatar
Fabrice Bellard committed
    /* copy stream format */
    s->nb_streams = ic->nb_streams;
    for(i=0;i<ic->nb_streams;i++) {
        AVStream *st;
        st = av_mallocz(sizeof(AVFormatContext));
        memcpy(st, ic->streams[i], sizeof(AVStream));
        s->streams[i] = st;
    }

    av_close_input_file(ic);
    return 0;
}

#define MAX_AUDIO_PACKET_SIZE 16384

static void do_audio_out(AVFormatContext *s, 
                         AVOutputStream *ost, 
                         AVInputStream *ist,
                         unsigned char *buf, int size)
{
    UINT8 *buftmp;
    UINT8 audio_buf[2*MAX_AUDIO_PACKET_SIZE]; /* XXX: allocate it */
    UINT8 audio_out[MAX_AUDIO_PACKET_SIZE]; /* XXX: allocate it */
    int size_out, frame_bytes, ret;
    AVCodecContext *enc;

    enc = &ost->st->codec;

    if (ost->audio_resample) {
        buftmp = audio_buf;
        size_out = audio_resample(ost->resample, 
                                  (short *)buftmp, (short *)buf,
                                  size / (ist->st->codec.channels * 2));
        size_out = size_out * enc->channels * 2;
    } else {
        buftmp = buf;
        size_out = size;
    }

    /* now encode as many frames as possible */
    if (enc->frame_size > 1) {
Fabrice Bellard's avatar
Fabrice Bellard committed
        /* output resampled raw samples */
        fifo_write(&ost->fifo, buftmp, size_out, 
                   &ost->fifo.wptr);

        frame_bytes = enc->frame_size * 2 * enc->channels;
        
        while (fifo_read(&ost->fifo, audio_buf, frame_bytes, 
                     &ost->fifo.rptr) == 0) {
            ret = avcodec_encode_audio(enc, audio_out, sizeof(audio_out), 
                                       (short *)audio_buf);
            av_write_frame(s, ost->index, audio_out, ret);
Fabrice Bellard's avatar
Fabrice Bellard committed
        }
    } else {
        /* output a pcm frame */
        /* XXX: change encoding codec API to avoid this ? */
        switch(enc->codec->id) {
        case CODEC_ID_PCM_S16LE:
        case CODEC_ID_PCM_S16BE:
        case CODEC_ID_PCM_U16LE:
        case CODEC_ID_PCM_U16BE:
            break;
        default:
            size_out = size_out >> 1;
            break;
        }
        ret = avcodec_encode_audio(enc, audio_out, size_out, 
                                   (short *)buftmp);
        av_write_frame(s, ost->index, audio_out, ret);
Fabrice Bellard's avatar
Fabrice Bellard committed
    }
}

/* write a picture to a raw mux */
static void write_picture(AVFormatContext *s, int index, AVPicture *picture, 
                          int pix_fmt, int w, int h)
Fabrice Bellard's avatar
Fabrice Bellard committed
{
    UINT8 *buf, *src, *dest;
    int size, j, i;
Fabrice Bellard's avatar
Fabrice Bellard committed
    /* XXX: not efficient, should add test if we can take
       directly the AVPicture */
    switch(pix_fmt) {
    case PIX_FMT_YUV420P:
        size = avpicture_get_size(pix_fmt, w, h);
Fabrice Bellard's avatar
Fabrice Bellard committed
        buf = av_malloc(size);
Loading
Loading full blame...