ffmpeg.c
来自「FFmpeg是用于录制、转换和流化音频和视频的完整解决方案」· C语言 代码 · 共 1,804 行 · 第 1/5 页
C
1,804 行
nb_frames_dup, nb_frames_drop); if (verbose >= 0) fprintf(stderr, "%s \r", buf); fflush(stderr); } if (is_last_report && verbose >= 0){ int64_t raw= audio_size + video_size + extra_size; fprintf(stderr, "\n"); fprintf(stderr, "video:%1.0fkB audio:%1.0fkB global headers:%1.0fkB muxing overhead %f%%\n", video_size/1024.0, audio_size/1024.0, extra_size/1024.0, 100.0*(total_size - raw)/raw ); }}/* pkt = NULL means EOF (needed to flush decoder buffers) */static int output_packet(AVInputStream *ist, int ist_index, AVOutputStream **ost_table, int nb_ostreams, const AVPacket *pkt){ AVFormatContext *os; AVOutputStream *ost; uint8_t *ptr; int len, ret, i; uint8_t *data_buf; int data_size, got_picture; AVFrame picture; void *buffer_to_free; static int samples_size= 0; static short *samples= NULL; if(!pkt){ ist->pts= ist->next_pts; // needed for last packet if vsync=0 } else if (pkt->dts != AV_NOPTS_VALUE) { //FIXME seems redundant, as libavformat does this too ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); } else {// assert(ist->pts == ist->next_pts); } if (pkt == NULL) { /* EOF handling */ ptr = NULL; len = 0; goto handle_eof; } len = pkt->size; ptr = pkt->data; while (len > 0) { handle_eof: /* decode the packet if needed */ data_buf = NULL; /* fail safe */ data_size = 0; if (ist->decoding_needed) { switch(ist->st->codec.codec_type) { case CODEC_TYPE_AUDIO:{ if(pkt) samples= av_fast_realloc(samples, &samples_size, FFMAX(pkt->size, AVCODEC_MAX_AUDIO_FRAME_SIZE)); /* XXX: could avoid copy if PCM 16 bits with same endianness as CPU */ ret = avcodec_decode_audio(&ist->st->codec, samples, &data_size, ptr, len); if (ret < 0) goto fail_decode; ptr += ret; len -= ret; /* Some bug in mpeg audio decoder gives */ /* data_size < 0, it seems they are overflows */ if (data_size <= 0) { /* no audio frame */ continue; } data_buf = (uint8_t *)samples; ist->next_pts += ((int64_t)AV_TIME_BASE/2 * data_size) / (ist->st->codec.sample_rate * ist->st->codec.channels); break;} case CODEC_TYPE_VIDEO: data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2; /* XXX: allocate picture correctly */ avcodec_get_frame_defaults(&picture); ret = avcodec_decode_video(&ist->st->codec, &picture, &got_picture, ptr, len); ist->st->quality= picture.quality; if (ret < 0) goto fail_decode; if (!got_picture) { /* no picture yet */ goto discard_packet; } if (ist->st->codec.time_base.num != 0) { ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec.time_base.num) / ist->st->codec.time_base.den; } len = 0; break; default: goto fail_decode; } } else { switch(ist->st->codec.codec_type) { case CODEC_TYPE_AUDIO: ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec.frame_size) / (ist->st->codec.sample_rate * ist->st->codec.channels); break; case CODEC_TYPE_VIDEO: if (ist->st->codec.time_base.num != 0) { ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec.time_base.num) / ist->st->codec.time_base.den; } break; } data_buf = ptr; data_size = len; ret = len; len = 0; } buffer_to_free = NULL; if (ist->st->codec.codec_type == CODEC_TYPE_VIDEO) { pre_process_video_frame(ist, (AVPicture *)&picture, &buffer_to_free); } // preprocess audio (volume) if (ist->st->codec.codec_type == CODEC_TYPE_AUDIO) { if (audio_volume != 256) { short *volp; volp = samples; for(i=0;i<(data_size / sizeof(short));i++) { int v = ((*volp) * audio_volume + 128) >> 8; if (v < -32768) v = -32768; if (v > 32767) v = 32767; *volp++ = v; } } } /* frame rate emulation */ if (ist->st->codec.rate_emu) { int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.time_base.num, 1000000, ist->st->codec.time_base.den); int64_t now = av_gettime() - ist->start; if (pts > now) usleep(pts - now); ist->frame++; }#if 0 /* mpeg PTS deordering : if it is a P or I frame, the PTS is the one of the next displayed one */ /* XXX: add mpeg4 too ? */ if (ist->st->codec.codec_id == CODEC_ID_MPEG1VIDEO) { if (ist->st->codec.pict_type != B_TYPE) { int64_t tmp; tmp = ist->last_ip_pts; ist->last_ip_pts = ist->frac_pts.val; ist->frac_pts.val = tmp; } }#endif /* if output time reached then transcode raw format, encode packets and output them */ if (start_time == 0 || ist->pts >= start_time) for(i=0;i<nb_ostreams;i++) { int frame_size; ost = ost_table[i]; if (ost->source_index == ist_index) { os = output_files[ost->file_index];#if 0 printf("%d: got pts=%0.3f %0.3f\n", i, (double)pkt->pts / AV_TIME_BASE, ((double)ist->pts / AV_TIME_BASE) - ((double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den));#endif /* set the input output pts pairs */ ost->sync_ipts = (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/ AV_TIME_BASE; if (ost->encoding_needed) { switch(ost->st->codec.codec_type) { case CODEC_TYPE_AUDIO: do_audio_out(os, ost, ist, data_buf, data_size); break; case CODEC_TYPE_VIDEO: do_video_out(os, ost, ist, &picture, &frame_size); video_size += frame_size; if (do_vstats && frame_size) do_video_stats(os, ost, frame_size); break; default: av_abort(); } } else { AVFrame avframe; //FIXME/XXX remove this AVPacket opkt; av_init_packet(&opkt); /* no reencoding needed : output the packet directly */ /* force the input stream PTS */ avcodec_get_frame_defaults(&avframe); ost->st->codec.coded_frame= &avframe; avframe.key_frame = pkt->flags & PKT_FLAG_KEY; if(ost->st->codec.codec_type == CODEC_TYPE_AUDIO) audio_size += data_size; else if (ost->st->codec.codec_type == CODEC_TYPE_VIDEO) { video_size += data_size; ost->sync_opts++; } opkt.stream_index= ost->index; opkt.data= data_buf; opkt.size= data_size; if(pkt->pts != AV_NOPTS_VALUE) opkt.pts= av_rescale_q(av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base); else opkt.pts= AV_NOPTS_VALUE; opkt.dts= av_rescale_q(av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base); opkt.flags= pkt->flags; av_interleaved_write_frame(os, &opkt); ost->st->codec.frame_number++; ost->frame_number++; } } } av_free(buffer_to_free); } discard_packet: if (pkt == NULL) { /* EOF handling */ for(i=0;i<nb_ostreams;i++) { ost = ost_table[i]; if (ost->source_index == ist_index) { AVCodecContext *enc= &ost->st->codec; os = output_files[ost->file_index]; if(ost->st->codec.codec_type == CODEC_TYPE_AUDIO && enc->frame_size <=1) continue; if(ost->st->codec.codec_type == CODEC_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE)) continue; if (ost->encoding_needed) { for(;;) { AVPacket pkt; av_init_packet(&pkt); pkt.stream_index= ost->index; switch(ost->st->codec.codec_type) { case CODEC_TYPE_AUDIO: ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL); audio_size += ret; pkt.flags |= PKT_FLAG_KEY; break; case CODEC_TYPE_VIDEO: ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL); video_size += ret; if(enc->coded_frame && enc->coded_frame->key_frame) pkt.flags |= PKT_FLAG_KEY; if (ost->logfile && enc->stats_out) { fprintf(ost->logfile, "%s", enc->stats_out); } break; default: ret=-1; } if(ret<=0) break; pkt.data= bit_buffer; pkt.size= ret; if(enc->coded_frame) pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); av_interleaved_write_frame(os, &pkt); } } } } } return 0; fail_decode: return -1;}/* * The following code is the main loop of the file converter */static int av_encode(AVFormatContext **output_files, int nb_output_files, AVFormatContext **input_files, int nb_input_files, AVStreamMap *stream_maps, int nb_stream_maps){ int ret, i, j, k, n, nb_istreams = 0, nb_ostreams = 0; AVFormatContext *is, *os; AVCodecContext *codec, *icodec; AVOutputStream *ost, **ost_table = NULL; AVInputStream *ist, **ist_table = NULL; AVInputFile *file_table; AVFormatContext *stream_no_data; int key; file_table= (AVInputFile*) av_mallocz(nb_input_files * sizeof(AVInputFile)); if (!file_table) goto fail; /* input stream init */ j = 0; for(i=0;i<nb_input_files;i++) { is = input_files[i]; file_table[i].ist_index = j; file_table[i].nb_streams = is->nb_streams; j += is->nb_streams; } nb_istreams = j; ist_table = av_mallocz(nb_istreams * sizeof(AVInputStream *)); if (!ist_table) goto fail; for(i=0;i<nb_istreams;i++) { ist = av_mallocz(sizeof(AVInputStream)); if (!ist) goto fail; ist_table[i] = ist; } j = 0; for(i=0;i<nb_input_files;i++) { is = input_files[i]; for(k=0;k<is->nb_streams;k++) { ist = ist_table[j++]; ist->st = is->streams[k]; ist->file_index = i; ist->index = k; ist->discard = 1; /* the stream is discarded by default (changed later) */ if (ist->st->codec.rate_emu) { ist->start = av_gettime(); ist->frame = 0; } } } /* output stream init */ nb_ostreams = 0; for(i=0;i<nb_output_files;i++) { os = output_files[i];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?