📄 ffmpeg.c
字号:
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.frame_rate_base != 0) { ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec.frame_rate_base) / ist->st->codec.frame_rate; } len = 0; break; default: goto fail_decode; } } else { 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); } /* frame rate emulation */ if (ist->st->codec.rate_emu) { int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.frame_rate_base, 1000000, ist->st->codec.frame_rate); 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])/ 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: /* find an audio stream for synchro */ { int i; AVOutputStream *audio_sync, *ost1; audio_sync = NULL; for(i=0;i<nb_ostreams;i++) { ost1 = ost_table[i]; if (ost1->file_index == ost->file_index && ost1->st->codec.codec_type == CODEC_TYPE_AUDIO) { audio_sync = ost1; break; } } 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; opkt.stream_index= ost->index; opkt.data= data_buf; opkt.size= data_size; opkt.pts= pkt->pts + input_files_ts_offset[ist->file_index]; opkt.dts= pkt->dts + input_files_ts_offset[ist->file_index]; 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, VIDEO_BUFFER_SIZE, NULL); audio_size += ret; pkt.flags |= PKT_FLAG_KEY; break; case CODEC_TYPE_VIDEO: ret = avcodec_encode_video(enc, bit_buffer, VIDEO_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= enc->coded_frame->pts; 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; if (!bit_buffer) bit_buffer = av_malloc(VIDEO_BUFFER_SIZE); if (!bit_buffer) 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]; nb_ostreams += os->nb_streams; } if (nb_stream_maps > 0 && nb_stream_maps != nb_ostreams) { fprintf(stderr, "Number of stream maps must match number of output streams\n"); exit(1); } /* Sanity check the mapping args -- do the input files & streams exist? */ for(i=0;i<nb_stream_maps;i++) { int fi = stream_maps[i].file_index; int si = stream_maps[i].stream_index; if (fi < 0 || fi > nb_input_files - 1 || si < 0 || si > file_table[fi].nb_streams - 1) { fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si); exit(1); } } ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams); if (!ost_table) goto fail; for(i=0;i<nb_ostreams;i++) { ost = av_mallocz(sizeof(AVOutputStream)); if (!ost) goto fail; ost_table[i] = ost; } n = 0; for(k=0;k<nb_output_files;k++) { os = output_files[k]; for(i=0;i<os->nb_streams;i++) { int found; ost = ost_table[n++]; ost->file_index = k; ost->index = i; ost->st = os->streams[i]; if (nb_stream_maps > 0) { ost->source_index = file_table[stream_maps[n-1].file_index].ist_index + stream_maps[n-1].stream_index; /* Sanity check that the stream types match */ if (ist_table[ost->source_index]->st->codec.codec_type != ost->st->codec.codec_type) { fprintf(stderr, "Codec type mismatch for mapping #%d.%d -> #%d.%d\n", stream_maps[n-1].file_index, stream_maps[n-1].stream_index, ost->file_index, ost->index); exit(1); } } else { /* get corresponding input stream index : we select the first one with the right type */ found = 0; for(j=0;j<nb_istreams;j++) { ist = ist_table[j]; if (ist->discard && ist->st->codec.codec_type == ost->st->codec.codec_type) { ost->source_index = j; found = 1; } } if (!found) { /* try again and reuse existing stream */ for(j=0;j<nb_istreams;j++) { ist = ist_table[j]; if (ist->st->codec.codec_type == ost->st->codec.codec_type) { ost->source_index = j; found = 1; } } if (!found) { fprintf(stderr, "Could not find input stream matching output stream #%d.%d\n", ost->file_index, ost->index); exit(1); } } } ist = ist_table[ost->source_index]; ist->discard = 0; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -