Ticket #928: uglyFix.c

File uglyFix.c, 6.8 KB (added by Zax, 5 years ago)
Line 
1static double get_sync_ipts(const OutputStream *ost)
2{
3    const InputStream *ist = ost->sync_ist;
4    OutputFile *of = &output_files[ost->file_index];
5
6        ost->sync_ist->pts = fabs(ost->sync_ist->pts);
7
8        fprintf(stderr, "ist->pts:%ld, of->start_time:%ld, [ost->file_index]: %d, AV_TIME_BASE:%d\n", ist->pts, of->start_time, ost->file_index, AV_TIME_BASE);
9    return (double)(ist->pts - of->start_time) / AV_TIME_BASE;
10}
11
12
13static void do_video_out(AVFormatContext *s,
14                         OutputStream *ost,
15                         InputStream *ist,
16                         AVFrame *in_picture,
17                         int *frame_size, float quality)
18{
19    int nb_frames, i, ret, format_video_sync;
20    AVFrame *final_picture;
21    AVCodecContext *enc;
22    double sync_ipts;
23    double duration = 0;
24
25    enc = ost->st->codec;
26
27    if (ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE) {
28        duration = FFMAX(av_q2d(ist->st->time_base), av_q2d(ist->st->codec->time_base));
29        if(ist->st->avg_frame_rate.num)
30            duration= FFMAX(duration, 1/av_q2d(ist->st->avg_frame_rate));
31
32        duration /= av_q2d(enc->time_base);
33    }
34
35        double tmpSync_ipts = get_sync_ipts(ost);
36    sync_ipts = tmpSync_ipts / av_q2d(enc->time_base);
37        fprintf(stderr, "sync_ipts:%f, get_sync_ipts(ost):%f, av_q2d(enc->time_base):%f\n", sync_ipts, tmpSync_ipts, av_q2d(enc->time_base));
38
39    /* by default, we output a single frame */
40    nb_frames = 1;
41
42    *frame_size = 0;
43
44    format_video_sync = video_sync_method;
45    if (format_video_sync == VSYNC_AUTO)
46        format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : 1;
47
48    if (format_video_sync != VSYNC_PASSTHROUGH) {
49        double vdelta = sync_ipts - ost->sync_opts + duration;
50        // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
51        if (vdelta < -1.1)
52            nb_frames = 0;
53        else if (format_video_sync == VSYNC_VFR) {
54            if (vdelta <= -0.6) {
55                nb_frames = 0;
56            } else if (vdelta > 0.6)
57                ost->sync_opts = lrintf(sync_ipts);
58        } /*else if (fabs(vdelta) > 1.1)
59            nb_frames = lrintf(vdelta);
60fprintf(stderr, "vdelta:%f = sync_ipts:%f, ost->sync_opts:%"PRId64", duration:%f nb_frames:%d\n", vdelta, sync_ipts, ost->sync_opts, duration, nb_frames);
61        //av_log(NULL, AV_LOG_VERBOSE, "vdelta [ffmpeg]\n");
62        if (nb_frames == 0) {
63            ++nb_frames_drop;
64            av_log(NULL, AV_LOG_VERBOSE, "*** drop! [ffmpeg]\n");
65        } else if (nb_frames > 1) {
66            nb_frames_dup += nb_frames - 1;
67            av_log(NULL, AV_LOG_VERBOSE, "*** %d dup! [ffmpeg]\n", nb_frames - 1);
68        }*/nb_frames = 1;
69    } else
70        ost->sync_opts = lrintf(sync_ipts);
71
72    nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
73    if (nb_frames <= 0)
74        return;
75
76    do_video_resample(ost, ist, in_picture, &final_picture);
77
78    /* duplicates frame if needed */
79    for (i = 0; i < nb_frames; i++) {
80        AVPacket pkt;
81        av_init_packet(&pkt);
82        pkt.stream_index = ost->index;
83
84        if (s->oformat->flags & AVFMT_RAWPICTURE &&
85            enc->codec->id == CODEC_ID_RAWVIDEO) {
86            /* raw pictures are written as AVPicture structure to
87               avoid any copies. We support temporarily the older
88               method. */
89            enc->coded_frame->interlaced_frame = in_picture->interlaced_frame;
90            enc->coded_frame->top_field_first  = in_picture->top_field_first;
91            pkt.data   = (uint8_t *)final_picture;
92            pkt.size   =  sizeof(AVPicture);
93            pkt.pts    = av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base);
94            pkt.flags |= AV_PKT_FLAG_KEY;
95
96            write_frame(s, &pkt, ost);
97        } else {
98            AVFrame big_picture;
99
100            big_picture = *final_picture;
101            /* better than nothing: use input picture interlaced
102               settings */
103            big_picture.interlaced_frame = in_picture->interlaced_frame;
104            if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) {
105                if (ost->top_field_first == -1)
106                    big_picture.top_field_first = in_picture->top_field_first;
107                else
108                    big_picture.top_field_first = !!ost->top_field_first;
109            }
110
111            /* handles same_quant here. This is not correct because it may
112               not be a global option */
113            big_picture.quality = quality;
114            if (!enc->me_threshold)
115                big_picture.pict_type = 0;
116//            big_picture.pts = AV_NOPTS_VALUE;
117            big_picture.pts = ost->sync_opts;
118//            big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);
119// av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);
120            if (ost->forced_kf_index < ost->forced_kf_count &&
121                big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
122                big_picture.pict_type = AV_PICTURE_TYPE_I;
123                ost->forced_kf_index++;
124            }
125            ret = avcodec_encode_video(enc,
126                                       bit_buffer, bit_buffer_size,
127                                       &big_picture);
128            if (ret < 0) {
129                av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
130                exit_program(1);
131            }
132
133            if (ret > 0) {
134                pkt.data = bit_buffer;
135                pkt.size = ret;
136                if (enc->coded_frame->pts != AV_NOPTS_VALUE)
137                    pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
138/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n",
139   pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1,
140   pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/
141
142                if (enc->coded_frame->key_frame)
143                    pkt.flags |= AV_PKT_FLAG_KEY;
144                write_frame(s, &pkt, ost);
145                *frame_size = ret;
146                video_size += ret;
147                // fprintf(stderr,"\nFrame: %3d size: %5d type: %d",
148                //         enc->frame_number-1, ret, enc->pict_type);
149                /* if two pass, output log */
150                if (ost->logfile && enc->stats_out) {
151                    fprintf(ost->logfile, "%s", enc->stats_out);
152                }
153            }
154        }
155        ost->sync_opts++;
156        /*
157         * For video, number of frames in == number of packets out.
158         * But there may be reordering, so we can't throw away frames on encoder
159         * flush, we need to limit them here, before they go into encoder.
160         */
161        ost->frame_number++;
162    }
163}