Newer
Older
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
* 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.
* This library is distributed in the hope that it will be useful,
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define HAVE_AV_CONFIG_H
#include "avformat.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <termios.h>
#include <time.h>
#include <ctype.h>
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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;
Michael Niedermayer
committed
static int frame_topBand = 0;
static int frame_bottomBand = 0;
static int frame_leftBand = 0;
static int frame_rightBand = 0;
static int video_bit_rate = 200*1000;
static int video_bit_rate_tolerance = 4000*1000;
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;
Michael Niedermayer
committed
static float video_i_qfactor = -0.8;
static int video_disable = 0;
static int video_codec_id = CODEC_ID_NONE;
static int same_quality = 0;
static int use_hq = 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 idct_algo = 0;
static int use_part = 0;
static int packet_size = 0;
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;
static int do_hex_dump = 0;
static int do_play = 0;
static int do_psnr = 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"
#if !defined(CONFIG_AUDIO_OSS) && !defined(CONFIG_AUDIO_BEOS)
const char *audio_device = "none";
#endif
#ifndef CONFIG_VIDEO4LINUX
const char *v4l_device = "none";
#endif
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 */
Fabrice Bellard
committed
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;
/* 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 */
} 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 */
Fabrice Bellard
committed
int frame_decoded; /* true if a video or audio frame has been decoded */
} 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 */
/* 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);
#ifdef CONFIG_BEOS_NETSERVER
fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
#endif
}
/* read a key without blocking */
static int read_key(void)
{
int n = 1;
#ifndef CONFIG_BEOS_NETSERVER
struct timeval tv;
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);
#endif
n = read(0, &ch, 1);
if (n == 1)
return n;
#else
/* no interactive support */
static void term_exit(void)
}
static void term_init(void)
{
}
static int read_key(void)
{
return 0;
#endif
int read_ffserver_streams(AVFormatContext *s, const char *filename)
{
int i, err;
err = av_open_input_file(&ic, filename, NULL, FFM_PACKET_SIZE, NULL);
if (err < 0)
return err;
/* 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[4*MAX_AUDIO_PACKET_SIZE]; /* XXX: allocate it - yep really WMA */
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) {
/* 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);
Fabrice Bellard
committed
av_write_frame(s, ost->index, audio_out, ret);
/* 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);
Fabrice Bellard
committed
av_write_frame(s, ost->index, audio_out, ret);
static void write_picture(AVFormatContext *s, int index, AVPicture *picture,
int pix_fmt, int w, int h)
/* 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);
if (!buf)
return;
dest = buf;
for(i=0;i<3;i++) {
if (i == 1) {
w >>= 1;
h >>= 1;
}
src = picture->data[i];
for(j=0;j<h;j++) {
memcpy(dest, src, w);
dest += w;
src += picture->linesize[i];
}
}
break;
case PIX_FMT_YUV422P:
size = (w * h) * 2;
if (!buf)
return;
dest = buf;
for(i=0;i<3;i++) {
if (i == 1) {
w >>= 1;
}
src = picture->data[i];
for(j=0;j<h;j++) {
memcpy(dest, src, w);
dest += w;
src += picture->linesize[i];
}
}
break;
case PIX_FMT_YUV444P:
size = (w * h) * 3;
if (!buf)
return;
dest = buf;
for(i=0;i<3;i++) {
src = picture->data[i];
for(j=0;j<h;j++) {
memcpy(dest, src, w);
dest += w;
src += picture->linesize[i];
}
}
break;
case PIX_FMT_YUV422:
size = (w * h) * 2;
if (!buf)
return;
dest = buf;
src = picture->data[0];
for(j=0;j<h;j++) {
memcpy(dest, src, w * 2);
dest += w * 2;
src += picture->linesize[0];
break;
case PIX_FMT_RGB24:
case PIX_FMT_BGR24:
size = (w * h) * 3;
if (!buf)
return;
dest = buf;
src = picture->data[0];
memcpy(dest, src, w * 3);
dest += w * 3;
src += picture->linesize[0];
break;
default:
return;
Fabrice Bellard
committed
av_write_frame(s, index, buf, size);
Fabrice Bellard
committed
/* we begin to correct av delay at this threshold */
#define AV_DELAY_MAX 0.100
static void do_video_out(AVFormatContext *s,
AVOutputStream *ost,
AVInputStream *ist,
Loading
Loading full blame...