Commit 1ee56bf09afe357467cce5e90d1f2c7638afed9d
1 parent
f330d4d8
fix timestamps for keyframesGallery
Showing
1 changed file
with
41 additions
and
10 deletions
openbr/plugins/gallery/keyframes.cpp
| @@ -59,6 +59,7 @@ public: | @@ -59,6 +59,7 @@ public: | ||
| 59 | fps = 0.f; | 59 | fps = 0.f; |
| 60 | time_base = 0.f; | 60 | time_base = 0.f; |
| 61 | idx = 0; | 61 | idx = 0; |
| 62 | + idxOffset = -1; | ||
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | ~keyframesGallery() | 65 | ~keyframesGallery() |
| @@ -95,6 +96,9 @@ public: | @@ -95,6 +96,9 @@ public: | ||
| 95 | frame = av_frame_alloc(); | 96 | frame = av_frame_alloc(); |
| 96 | cvt_frame = av_frame_alloc(); | 97 | cvt_frame = av_frame_alloc(); |
| 97 | 98 | ||
| 99 | + av_init_packet(&packet); | ||
| 100 | + packet.data = NULL; | ||
| 101 | + packet.size = 0; | ||
| 98 | // Get fps, stream time_base and allocate space for frame buffer with av_malloc. | 102 | // Get fps, stream time_base and allocate space for frame buffer with av_malloc. |
| 99 | fps = (float)avFormatCtx->streams[streamID]->avg_frame_rate.num / | 103 | fps = (float)avFormatCtx->streams[streamID]->avg_frame_rate.num / |
| 100 | (float)avFormatCtx->streams[streamID]->avg_frame_rate.den; | 104 | (float)avFormatCtx->streams[streamID]->avg_frame_rate.den; |
| @@ -128,26 +132,50 @@ public: | @@ -128,26 +132,50 @@ public: | ||
| 128 | Template output; | 132 | Template output; |
| 129 | output.file = file; | 133 | output.file = file; |
| 130 | 134 | ||
| 131 | - AVPacket packet; | ||
| 132 | - av_init_packet(&packet); | 135 | + |
| 133 | int ret = 0; | 136 | int ret = 0; |
| 134 | while (!ret) { | 137 | while (!ret) { |
| 135 | if (av_read_frame(avFormatCtx, &packet) >= 0) { | 138 | if (av_read_frame(avFormatCtx, &packet) >= 0) { |
| 136 | if (packet.stream_index == streamID) { | 139 | if (packet.stream_index == streamID) { |
| 137 | avcodec_decode_video2(avCodecCtx, frame, &ret, &packet); | 140 | avcodec_decode_video2(avCodecCtx, frame, &ret, &packet); |
| 138 | - idx = packet.dts; // decompression timestamp | 141 | + // Use presentation timestamp if available |
| 142 | + // Otherwise decode timestamp | ||
| 143 | + if (frame->pkt_pts != AV_NOPTS_VALUE) | ||
| 144 | + idx = frame->pkt_pts; | ||
| 145 | + else | ||
| 146 | + idx = frame->pkt_dts; | ||
| 147 | + | ||
| 139 | av_free_packet(&packet); | 148 | av_free_packet(&packet); |
| 140 | } else { | 149 | } else { |
| 141 | av_free_packet(&packet); | 150 | av_free_packet(&packet); |
| 142 | } | 151 | } |
| 143 | } else { | 152 | } else { |
| 144 | - av_free_packet(&packet); | ||
| 145 | - release(); | ||
| 146 | - *done = true; | ||
| 147 | - return TemplateList(); | 153 | + AVPacket empty_packet; |
| 154 | + av_init_packet(&empty_packet); | ||
| 155 | + empty_packet.data = NULL; | ||
| 156 | + empty_packet.size = 0; | ||
| 157 | + | ||
| 158 | + avcodec_decode_video2(avCodecCtx, frame, &ret, &empty_packet); | ||
| 159 | + if (frame->pkt_pts != AV_NOPTS_VALUE) | ||
| 160 | + idx = frame->pkt_pts; | ||
| 161 | + else if (frame->pkt_dts != AV_NOPTS_VALUE) | ||
| 162 | + idx = frame->pkt_dts; | ||
| 163 | + else // invalid frame | ||
| 164 | + ret = 0; | ||
| 165 | + | ||
| 166 | + if (!ret) { | ||
| 167 | + av_free_packet(&packet); | ||
| 168 | + av_free_packet(&empty_packet); | ||
| 169 | + release(); | ||
| 170 | + *done = true; | ||
| 171 | + return TemplateList(); | ||
| 172 | + } | ||
| 148 | } | 173 | } |
| 149 | } | 174 | } |
| 150 | 175 | ||
| 176 | + if (idxOffset < 0) { | ||
| 177 | + idxOffset = idx; | ||
| 178 | + } | ||
| 151 | // Convert from native format | 179 | // Convert from native format |
| 152 | sws_scale(avSwsCtx, | 180 | sws_scale(avSwsCtx, |
| 153 | frame->data, | 181 | frame->data, |
| @@ -164,9 +192,9 @@ public: | @@ -164,9 +192,9 @@ public: | ||
| 164 | avcodec_flush_buffers(avCodecCtx); | 192 | avcodec_flush_buffers(avCodecCtx); |
| 165 | 193 | ||
| 166 | QString URL = file.get<QString>("URL", file.name); | 194 | QString URL = file.get<QString>("URL", file.name); |
| 167 | - output.file.set("URL", URL + "#t=" + QString::number((int)(idx * time_base)) + "s"); | ||
| 168 | - output.file.set("timestamp", QString::number((int)(idx * time_base * 1000))); | ||
| 169 | - output.file.set("frame", QString::number(idx * time_base * fps)); | 195 | + output.file.set("URL", URL + "#t=" + QString::number((int)((idx-idxOffset) * time_base)) + "s"); |
| 196 | + output.file.set("timestamp", QString::number((int)((idx-idxOffset) * time_base * 1000))); | ||
| 197 | + output.file.set("frame", QString::number((idx-idxOffset) * time_base * fps)); | ||
| 170 | TemplateList dst; | 198 | TemplateList dst; |
| 171 | dst.append(output); | 199 | dst.append(output); |
| 172 | return dst; | 200 | return dst; |
| @@ -204,7 +232,10 @@ protected: | @@ -204,7 +232,10 @@ protected: | ||
| 204 | AVCodec *avCodec; | 232 | AVCodec *avCodec; |
| 205 | AVFrame *frame; | 233 | AVFrame *frame; |
| 206 | AVFrame *cvt_frame; | 234 | AVFrame *cvt_frame; |
| 235 | + AVPacket packet; | ||
| 207 | uint8_t *buffer; | 236 | uint8_t *buffer; |
| 237 | + | ||
| 238 | + int64_t idxOffset; | ||
| 208 | bool opened; | 239 | bool opened; |
| 209 | int streamID; | 240 | int streamID; |
| 210 | float fps; | 241 | float fps; |