📄 ffmpeg.c
字号:
unsigned char ch;
#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
if (n > 0) {
n = read(0, &ch, 1);
if (n == 1)
return ch;
return n;
}
#elif defined(HAVE_CONIO_H)
if(kbhit())
return(getch());
#endif
return -1;
}
static int decode_interrupt_cb(void)
{
return q_pressed || (q_pressed = read_key() == 'q');
}
static int read_ffserver_streams(AVFormatContext *s, const char *filename)
{
int i, err;
AVFormatContext *ic;
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;
// FIXME: a more elegant solution is needed
st = av_mallocz(sizeof(AVStream));
memcpy(st, ic->streams[i], sizeof(AVStream));
st->codec = avcodec_alloc_context();
memcpy(st->codec, ic->streams[i]->codec, sizeof(AVCodecContext));
s->streams[i] = st;
}
av_close_input_file(ic);
return 0;
}
static double
get_sync_ipts(const AVOutputStream *ost)
{
const AVInputStream *ist = ost->sync_ist;
return (double)(ist->pts - start_time)/AV_TIME_BASE;
}
static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){
while(bsfc){
AVPacket new_pkt= *pkt;
int a= av_bitstream_filter_filter(bsfc, avctx, NULL,
&new_pkt.data, &new_pkt.size,
pkt->data, pkt->size,
pkt->flags & PKT_FLAG_KEY);
if(a){
av_free_packet(pkt);
new_pkt.destruct= av_destruct_packet;
}
*pkt= new_pkt;
bsfc= bsfc->next;
}
av_interleaved_write_frame(s, pkt);
}
#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
static void do_audio_out(AVFormatContext *s,
AVOutputStream *ost,
AVInputStream *ist,
unsigned char *buf, int size)
{
uint8_t *buftmp;
static uint8_t *audio_buf = NULL;
static uint8_t *audio_out = NULL;
const int audio_out_size= 4*MAX_AUDIO_PACKET_SIZE;
int size_out, frame_bytes, ret;
AVCodecContext *enc= ost->st->codec;
/* SC: dynamic allocation of buffers */
if (!audio_buf)
audio_buf = av_malloc(2*MAX_AUDIO_PACKET_SIZE);
if (!audio_out)
audio_out = av_malloc(audio_out_size);
if (!audio_buf || !audio_out)
return; /* Should signal an error ! */
if(audio_sync_method){
double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts
- av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2);
double idelta= delta*ist->st->codec->sample_rate / enc->sample_rate;
int byte_delta= ((int)idelta)*2*ist->st->codec->channels;
//FIXME resample delay
if(fabs(delta) > 50){
if(ist->is_start || fabs(delta) > audio_drift_threshold*enc->sample_rate){
if(byte_delta < 0){
byte_delta= FFMAX(byte_delta, -size);
size += byte_delta;
buf -= byte_delta;
if(verbose > 2)
fprintf(stderr, "discarding %d audio samples\n", (int)-delta);
if(!size)
return;
ist->is_start=0;
}else{
static uint8_t *input_tmp= NULL;
input_tmp= av_realloc(input_tmp, byte_delta + size);
if(byte_delta + size <= MAX_AUDIO_PACKET_SIZE)
ist->is_start=0;
else
byte_delta= MAX_AUDIO_PACKET_SIZE - size;
memset(input_tmp, 0, byte_delta);
memcpy(input_tmp + byte_delta, buf, size);
buf= input_tmp;
size += byte_delta;
if(verbose > 2)
fprintf(stderr, "adding %d audio samples of silence\n", (int)delta);
}
}else if(audio_sync_method>1){
int comp= av_clip(delta, -audio_sync_method, audio_sync_method);
assert(ost->audio_resample);
if(verbose > 2)
fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate);
// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2));
av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate);
}
}
}else
ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate)
- av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong
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 */
av_fifo_write(&ost->fifo, buftmp, size_out);
frame_bytes = enc->frame_size * 2 * enc->channels;
while (av_fifo_read(&ost->fifo, audio_buf, frame_bytes) == 0) {
AVPacket pkt;
av_init_packet(&pkt);
ret = avcodec_encode_audio(enc, audio_out, audio_out_size,
(short *)audio_buf);
audio_size += ret;
pkt.stream_index= ost->index;
pkt.data= audio_out;
pkt.size= ret;
if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
pkt.flags |= PKT_FLAG_KEY;
write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
ost->sync_opts += enc->frame_size;
}
} else {
AVPacket pkt;
av_init_packet(&pkt);
ost->sync_opts += size_out / (2 * enc->channels);
/* output a pcm frame */
/* XXX: change encoding codec API to avoid this ? */
switch(enc->codec->id) {
case CODEC_ID_PCM_S32LE:
case CODEC_ID_PCM_S32BE:
case CODEC_ID_PCM_U32LE:
case CODEC_ID_PCM_U32BE:
size_out = size_out << 1;
break;
case CODEC_ID_PCM_S24LE:
case CODEC_ID_PCM_S24BE:
case CODEC_ID_PCM_U24LE:
case CODEC_ID_PCM_U24BE:
case CODEC_ID_PCM_S24DAUD:
size_out = size_out / 2 * 3;
break;
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);
audio_size += ret;
pkt.stream_index= ost->index;
pkt.data= audio_out;
pkt.size= ret;
if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
pkt.flags |= PKT_FLAG_KEY;
write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
}
}
static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void **bufp)
{
AVCodecContext *dec;
AVPicture *picture2;
AVPicture picture_tmp;
uint8_t *buf = 0;
dec = ist->st->codec;
/* deinterlace : must be done before any resize */
if (do_deinterlace || using_vhook) {
int size;
/* create temporary picture */
size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height);
buf = av_malloc(size);
if (!buf)
return;
picture2 = &picture_tmp;
avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height);
if (do_deinterlace){
if(avpicture_deinterlace(picture2, picture,
dec->pix_fmt, dec->width, dec->height) < 0) {
/* if error, do not deinterlace */
av_free(buf);
buf = NULL;
picture2 = picture;
}
} else {
av_picture_copy(picture2, picture, dec->pix_fmt, dec->width, dec->height);
}
} else {
picture2 = picture;
}
if (ENABLE_VHOOK)
frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height,
1000000 * ist->pts / AV_TIME_BASE);
if (picture != picture2)
*picture = *picture2;
*bufp = buf;
}
/* we begin to correct av delay at this threshold */
#define AV_DELAY_MAX 0.100
static void do_subtitle_out(AVFormatContext *s,
AVOutputStream *ost,
AVInputStream *ist,
AVSubtitle *sub,
int64_t pts)
{
static uint8_t *subtitle_out = NULL;
int subtitle_out_max_size = 65536;
int subtitle_out_size, nb, i;
AVCodecContext *enc;
AVPacket pkt;
if (pts == AV_NOPTS_VALUE) {
fprintf(stderr, "Subtitle packets must have a pts\n");
return;
}
enc = ost->st->codec;
if (!subtitle_out) {
subtitle_out = av_malloc(subtitle_out_max_size);
}
/* Note: DVB subtitle need one packet to draw them and one other
packet to clear them */
/* XXX: signal it in the codec context ? */
if (enc->codec_id == CODEC_ID_DVB_SUBTITLE)
nb = 2;
else
nb = 1;
for(i = 0; i < nb; i++) {
subtitle_out_size = avcodec_encode_subtitle(enc, subtitle_out,
subtitle_out_max_size, sub);
av_init_packet(&pkt);
pkt.stream_index = ost->index;
pkt.data = subtitle_out;
pkt.size = subtitle_out_size;
pkt.pts = av_rescale_q(pts, ist->st->time_base, ost->st->time_base);
if (enc->codec_id == CODEC_ID_DVB_SUBTITLE) {
/* XXX: the pts correction is handled here. Maybe handling
it in the codec would be better */
if (i == 0)
pkt.pts += 90 * sub->start_display_time;
else
pkt.pts += 90 * sub->end_display_time;
}
write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
}
}
static int bit_buffer_size= 1024*256;
static uint8_t *bit_buffer= NULL;
static void do_video_out(AVFormatContext *s,
AVOutputStream *ost,
AVInputStream *ist,
AVFrame *in_picture,
int *frame_size)
{
int nb_frames, i, ret;
AVFrame *final_picture, *formatted_picture, *resampling_dst, *padding_src;
AVFrame picture_crop_temp, picture_pad_temp;
AVCodecContext *enc, *dec;
avcodec_get_frame_defaults(&picture_crop_temp);
avcodec_get_frame_defaults(&picture_pad_temp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -