ffmpeg.c
来自「FFmpeg是用于录制、转换和流化音频和视频的完整解决方案」· C语言 代码 · 共 1,804 行 · 第 1/5 页
C
1,804 行
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); signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */ signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */ signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */ /* register a function to be called at normal program termination */ 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; 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; } return -1;}static int decode_interrupt_cb(void){ return q_pressed || (q_pressed = read_key() == 'q');}#elsestatic volatile int received_sigterm = 0;/* no interactive support */static void term_exit(void){}static void term_init(void){}static int read_key(void){ return 0;}#endifstatic 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; st = av_mallocz(sizeof(AVStream)); memcpy(st, ic->streams[i], sizeof(AVStream)); s->streams[i] = st; } av_close_input_file(ic); return 0;}#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 = ost->sync_ipts * enc->sample_rate - ost->sync_opts - fifo_size(&ost->fifo, ost->fifo.rptr)/(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){ 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= 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:%lld ipts:%lld fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(ost->sync_ipts * enc->sample_rate), fifo_size(&ost->fifo, ost->fifo.rptr)/(ost->st->codec.channels * 2)); av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate); } } }else ost->sync_opts= lrintf(ost->sync_ipts * enc->sample_rate) - fifo_size(&ost->fifo, ost->fifo.rptr)/(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 */ 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) { 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) pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); pkt.flags |= PKT_FLAG_KEY; av_interleaved_write_frame(s, &pkt); 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_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) pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); pkt.flags |= PKT_FLAG_KEY; av_interleaved_write_frame(s, &pkt); }}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 { if (img_convert(picture2, dec->pix_fmt, picture, dec->pix_fmt, dec->width, dec->height) < 0) { /* if error, do not copy */ av_free(buf); buf = NULL; picture2 = picture; } } } else { picture2 = picture; } frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height); if (picture != picture2) *picture = *picture2; *bufp = buf;}/* we begin to correct av delay at this threshold */#define AV_DELAY_MAX 0.100/* Expects img to be yuv420 */static void fill_pad_region(AVPicture* img, int height, int width, int padtop, int padbottom, int padleft, int padright, int *color) { int i, y, shift; uint8_t *optr; for (i = 0; i < 3; i++) { shift = (i == 0) ? 0 : 1; if (padtop || padleft) { memset(img->data[i], color[i], (((img->linesize[i] * padtop) + padleft) >> shift)); } if (padleft || padright) { optr = img->data[i] + (img->linesize[i] * (padtop >> shift)) + (img->linesize[i] - (padright >> shift)); for (y = 0; y < ((height - (padtop + padbottom) - 1) >> shift); y++) { memset(optr, color[i], (padleft + padright) >> shift); optr += img->linesize[i]; } } if (padbottom || padright) { optr = img->data[i] + (((img->linesize[i] * (height - padbottom)) - padright) >> shift); memset(optr, color[i], (((img->linesize[i] * padbottom) + padright) >> shift)); } }}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; AVFrame picture_format_temp, picture_crop_temp; uint8_t *buf = NULL, *buf1 = NULL; AVCodecContext *enc, *dec; enum PixelFormat target_pixfmt; avcodec_get_frame_defaults(&picture_format_temp); avcodec_get_frame_defaults(&picture_crop_temp); enc = &ost->st->codec; dec = &ist->st->codec; /* by default, we output a single frame */ nb_frames = 1; *frame_size = 0; if(video_sync_method){ double vdelta; vdelta = ost->sync_ipts / av_q2d(enc->time_base) - ost->sync_opts; //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (vdelta < -1.1) nb_frames = 0; else if (vdelta > 1.1) nb_frames = lrintf(vdelta);//fprintf(stderr, "vdelta:%f, ost->sync_opts:%lld, ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, ost->sync_ipts, nb_frames); if (nb_frames == 0){ ++nb_frames_drop; if (verbose>2) fprintf(stderr, "*** drop!\n"); }else if (nb_frames > 1) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?