Ticket #928: uglyFix.c

File uglyFix.c, 6.8 KB (added by Zax, 14 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}