| 159 | } |
| 160 | |
| 161 | static void finish_stream(SyncQueue *sq, unsigned int stream_idx) |
| 162 | { |
| 163 | SyncQueueStream *st = &sq->streams[stream_idx]; |
| 164 | |
| 165 | if (!st->finished) |
| 166 | av_log(sq->logctx, AV_LOG_DEBUG, |
| 167 | "sq: finish %u; head ts %s\n", stream_idx, |
| 168 | av_ts2timestr(st->head_ts, &st->tb)); |
| 169 | |
| 170 | st->finished = 1; |
| 171 | |
| 172 | if (st->limiting && st->head_ts != AV_NOPTS_VALUE) { |
| 173 | /* check if this stream is the new finished head */ |
| 174 | if (sq->head_finished_stream < 0 || |
| 175 | av_compare_ts(st->head_ts, st->tb, |
| 176 | sq->streams[sq->head_finished_stream].head_ts, |
| 177 | sq->streams[sq->head_finished_stream].tb) < 0) { |
| 178 | sq->head_finished_stream = stream_idx; |
| 179 | } |
| 180 | |
| 181 | /* mark as finished all streams that should no longer receive new frames, |
| 182 | * due to them being ahead of some finished stream */ |
| 183 | st = &sq->streams[sq->head_finished_stream]; |
| 184 | for (unsigned int i = 0; i < sq->nb_streams; i++) { |
| 185 | SyncQueueStream *st1 = &sq->streams[i]; |
| 186 | if (st != st1 && st1->head_ts != AV_NOPTS_VALUE && |
| 187 | av_compare_ts(st->head_ts, st->tb, st1->head_ts, st1->tb) <= 0) { |
| 188 | if (!st1->finished) |
| 189 | av_log(sq->logctx, AV_LOG_DEBUG, |
| 190 | "sq: finish secondary %u; head ts %s\n", i, |
| 191 | av_ts2timestr(st1->head_ts, &st1->tb)); |
| 192 | |
| 193 | st1->finished = 1; |
| 194 | } |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | /* mark the whole queue as finished if all streams are finished */ |
| 199 | for (unsigned int i = 0; i < sq->nb_streams; i++) { |
| 200 | if (!sq->streams[i].finished) |
| 201 | return; |
| 202 | } |
| 203 | sq->finished = 1; |
| 204 | |
| 205 | av_log(sq->logctx, AV_LOG_DEBUG, "sq: finish queue\n"); |
| 206 | } |
| 207 | |
| 208 | static void queue_head_update(SyncQueue *sq) |
| 209 | { |
no test coverage detected