⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffmpeg.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 5 页
字号:
    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);    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 = get_sync_ipts(ost) / 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:%"PRId64", 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) {            nb_frames_dup += nb_frames;            if (verbose>2)                fprintf(stderr, "*** %d dup!\n", nb_frames-1);        }    }else        ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));    nb_frames= FFMIN(nb_frames, max_frames[CODEC_TYPE_VIDEO] - ost->frame_number);    if (nb_frames <= 0)        return;    if (ost->video_crop) {        if (av_picture_crop((AVPicture *)&picture_crop_temp, (AVPicture *)in_picture, dec->pix_fmt, ost->topBand, ost->leftBand) < 0) {            av_log(NULL, AV_LOG_ERROR, "error cropping picture\n");            return;        }        formatted_picture = &picture_crop_temp;    } else {        formatted_picture = in_picture;    }    final_picture = formatted_picture;    padding_src = formatted_picture;    resampling_dst = &ost->pict_tmp;    if (ost->video_pad) {        final_picture = &ost->pict_tmp;        if (ost->video_resample) {            if (av_picture_crop((AVPicture *)&picture_pad_temp, (AVPicture *)final_picture, enc->pix_fmt, ost->padtop, ost->padleft) < 0) {                av_log(NULL, AV_LOG_ERROR, "error padding picture\n");                return;            }            resampling_dst = &picture_pad_temp;        }    }    if (ost->video_resample) {        padding_src = NULL;        final_picture = &ost->pict_tmp;        sws_scale(ost->img_resample_ctx, formatted_picture->data, formatted_picture->linesize,              0, ost->resample_height, resampling_dst->data, resampling_dst->linesize);    }    if (ost->video_pad) {        av_picture_pad((AVPicture*)final_picture, (AVPicture *)padding_src,                enc->height, enc->width, enc->pix_fmt,                ost->padtop, ost->padbottom, ost->padleft, ost->padright, padcolor);    }    /* duplicates frame if needed */    for(i=0;i<nb_frames;i++) {        AVPacket pkt;        av_init_packet(&pkt);        pkt.stream_index= ost->index;        if (s->oformat->flags & AVFMT_RAWPICTURE) {            /* raw pictures are written as AVPicture structure to               avoid any copies. We support temorarily the older               method. */            AVFrame* old_frame = enc->coded_frame;            enc->coded_frame = dec->coded_frame; //FIXME/XXX remove this hack            pkt.data= (uint8_t *)final_picture;            pkt.size=  sizeof(AVPicture);            pkt.pts= av_rescale_q(ost->sync_opts, 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]);            enc->coded_frame = old_frame;        } else {            AVFrame big_picture;            big_picture= *final_picture;            /* better than nothing: use input picture interlaced               settings */            big_picture.interlaced_frame = in_picture->interlaced_frame;            if(avctx_opts[CODEC_TYPE_VIDEO]->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)){                if(top_field_first == -1)                    big_picture.top_field_first = in_picture->top_field_first;                else                    big_picture.top_field_first = top_field_first;            }            /* handles sameq here. This is not correct because it may               not be a global option */            if (same_quality) {                big_picture.quality = ist->st->quality;            }else                big_picture.quality = ost->st->quality;            if(!me_threshold)                big_picture.pict_type = 0;//            big_picture.pts = AV_NOPTS_VALUE;            big_picture.pts= ost->sync_opts;//            big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);//av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);            ret = avcodec_encode_video(enc,                                       bit_buffer, bit_buffer_size,                                       &big_picture);            if (ret == -1) {                fprintf(stderr, "Video encoding failed\n");                exit(1);            }            //enc->frame_number = enc->real_pict_num;            if(ret>0){                pkt.data= bit_buffer;                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);/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n",   pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1,   pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/                if(enc->coded_frame && enc->coded_frame->key_frame)                    pkt.flags |= PKT_FLAG_KEY;                write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);                *frame_size = ret;                //fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d",                //        enc->frame_number-1, enc->real_pict_num, ret,                //        enc->pict_type);                /* if two pass, output log */                if (ost->logfile && enc->stats_out) {                    fprintf(ost->logfile, "%s", enc->stats_out);                }            }        }        ost->sync_opts++;        ost->frame_number++;    }}static double psnr(double d){    if(d==0) return INFINITY;    return -10.0*log(d)/log(10.0);}static void do_video_stats(AVFormatContext *os, AVOutputStream *ost,                           int frame_size){    AVCodecContext *enc;    int frame_number;    double ti1, bitrate, avg_bitrate;    /* this is executed just the first time do_video_stats is called */    if (!vstats_file) {        vstats_file = fopen(vstats_filename, "w");        if (!vstats_file) {            perror("fopen");            exit(1);        }    }    enc = ost->st->codec;    if (enc->codec_type == CODEC_TYPE_VIDEO) {        frame_number = ost->frame_number;        fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality/(float)FF_QP2LAMBDA);        if (enc->flags&CODEC_FLAG_PSNR)            fprintf(vstats_file, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0]/(enc->width*enc->height*255.0*255.0)));        fprintf(vstats_file,"f_size= %6d ", frame_size);        /* compute pts value */        ti1 = ost->sync_opts * av_q2d(enc->time_base);        if (ti1 < 0.01)            ti1 = 0.01;        bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;        avg_bitrate = (double)(video_size * 8) / ti1 / 1000.0;        fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",            (double)video_size / 1024, ti1, bitrate, avg_bitrate);        fprintf(vstats_file,"type= %c\n", av_get_pict_type_char(enc->coded_frame->pict_type));    }}static void print_report(AVFormatContext **output_files,                         AVOutputStream **ost_table, int nb_ostreams,                         int is_last_report){    char buf[1024];    AVOutputStream *ost;    AVFormatContext *oc, *os;    int64_t total_size;    AVCodecContext *enc;    int frame_number, vid, i;    double bitrate, ti1, pts;    static int64_t last_time = -1;    static int qp_histogram[52];    if (!is_last_report) {        int64_t cur_time;        /* display the report every 0.5 seconds */        cur_time = av_gettime();        if (last_time == -1) {            last_time = cur_time;            return;        }        if ((cur_time - last_time) < 500000)            return;        last_time = cur_time;    }    oc = output_files[0];    total_size = url_fsize(oc->pb);    if(total_size<0) // FIXME improve url_fsize() so it works with non seekable output too        total_size= url_ftell(oc->pb);    buf[0] = '\0';    ti1 = 1e10;    vid = 0;    for(i=0;i<nb_ostreams;i++) {        ost = ost_table[i];        os = output_files[ost->file_index];        enc = ost->st->codec;        if (vid && enc->codec_type == CODEC_TYPE_VIDEO) {            snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ",                     enc->coded_frame && !ost->st->stream_copy ?                     enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);        }        if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {            float t = (av_gettime()-timer_start) / 1000000.0;            frame_number = ost->frame_number;            snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",                     frame_number, (t>1)?(int)(frame_number/t+0.5) : 0,                     enc->coded_frame && !ost->st->stream_copy ?                     enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);            if(is_last_report)                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");            if(qp_hist && enc->coded_frame){                int j;                int qp= lrintf(enc->coded_frame->quality/(float)FF_QP2LAMBDA);                if(qp>=0 && qp<sizeof(qp_histogram)/sizeof(int))                    qp_histogram[qp]++;                for(j=0; j<32; j++)                    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", (int)lrintf(log(qp_histogram[j]+1)/log(2)));            }            if (enc->flags&CODEC_FLAG_PSNR){                int j;                double error, error_sum=0;                double scale, scale_sum=0;                char type[3]= {'Y','U','V'};                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR=");                for(j=0; j<3; j++){                    if(is_last_report){                        error= enc->error[j];                        scale= enc->width*enc->height*255.0*255.0*frame_number;                    }else{                        error= enc->coded_frame->error[j];                        scale= enc->width*enc->height*255.0*255.0;                    }                    if(j) scale/=4;                    error_sum += error;                    scale_sum += scale;                    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], psnr(error/scale));                }                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum/scale_sum));            }            vid = 1;        }        /* compute min output value */        pts = (double)ost->st->pts.val * av_q2d(ost->st->time_base);        if ((pts < ti1) && (pts > 0))            ti1 = pts;    }    if (ti1 < 0.01)        ti1 = 0.01;    if (verbose || is_last_report) {        bitrate = (double)(total_size * 8) / ti1 / 1000.0;        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),            "size=%8.0fkB time=%0.1f bitrate=%6.1fkbits/s",            (double)total_size / 1024, ti1, bitrate);        if (verbose > 1)          snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",                  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 unsigned int samples_size= 0;    static short *samples= NULL;    AVSubtitle subtitle, *subtitle_to_free;    int got_subtitle;    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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -