📄 ffmpeg.c
字号:
#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 doubleget_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){ int ret; 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>0){ av_free_packet(pkt); new_pkt.destruct= av_destruct_packet; } else if(a<0){ fprintf(stderr, "%s failed for stream %d, codec %s", bsfc->filter->name, pkt->stream_index, avctx->codec ? avctx->codec->name : "copy"); print_error("", a); } *pkt= new_pkt; bsfc= bsfc->next; } ret= av_interleaved_write_frame(s, pkt); if(ret < 0){ print_error("av_interleaved_write_frame()", ret); exit(1); }}#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; AVCodecContext *dec= ist->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 (enc->channels != dec->channels) ost->audio_resample = 1; if (ost->audio_resample && !ost->resample) { ost->resample = audio_resample_init(enc->channels, dec->channels, enc->sample_rate, dec->sample_rate); if (!ost->resample) { fprintf(stderr, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n", dec->channels, dec->sample_rate, enc->channels, enc->sample_rate); exit(1); } } 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.100static 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -