mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-08-31 02:13:51 +08:00
obs-outputs: Do not drop last packet when flushing Hybrid file
Originally, before file splitting was introduced, I made the choice to simply ignore the last frame in the packet queue of the muxer, because frame N+1 is required to properly determine the duration and I figured nobody would notice if their recording is one frame short. However, when using frame splitting this would result in the last frame before the split being dropped. To fix this, we can simply reuse the previous sample's duration for the final sample in a file. Since OBS only does CFR, they should all be identical anyway.
This commit is contained in:
@@ -2501,18 +2501,30 @@ static void process_packets(struct mp4_mux *mux, struct mp4_track *track, uint64
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
/* Only iterate upt to penultimate packet so we can determine duration
|
||||
* for all processed packets. */
|
||||
for (size_t i = 0; i < count - 1; i++) {
|
||||
/* Unless it is the final flush, only iterate up to penultimate packet so we can determine duration for all
|
||||
* processed packets. */
|
||||
const bool final_flush = mux->next_frag_pts == 0;
|
||||
const size_t end_offset = final_flush ? 0 : 1;
|
||||
|
||||
for (size_t i = 0; i < count - end_offset; i++) {
|
||||
struct encoder_packet *pkt = get_pkt_at(&track->packets, i);
|
||||
|
||||
if (mux->next_frag_pts && packet_pts_usec(pkt) >= mux->next_frag_pts)
|
||||
if (!final_flush && packet_pts_usec(pkt) >= mux->next_frag_pts)
|
||||
break;
|
||||
|
||||
struct encoder_packet *next = get_pkt_at(&track->packets, i + 1);
|
||||
uint32_t duration;
|
||||
if (i < count - 1) {
|
||||
/* If a next packet is available: Duration is just distance between current and next DTS. */
|
||||
struct encoder_packet *next = get_pkt_at(&track->packets, i + 1);
|
||||
duration = (uint32_t)(next->dts - pkt->dts);
|
||||
} else {
|
||||
/* If this is the last packet, and we're doing a final flush: Reuse the previous duration */
|
||||
if (!track->fragment_samples.num)
|
||||
break; /* no previous sample */
|
||||
|
||||
duration = track->fragment_samples.array[track->fragment_samples.num - 1].duration;
|
||||
}
|
||||
|
||||
/* Duration is just distance between current and next DTS. */
|
||||
uint32_t duration = (uint32_t)(next->dts - pkt->dts);
|
||||
uint32_t sample_count = 1;
|
||||
uint32_t size = (uint32_t)pkt->size;
|
||||
int32_t offset = (int32_t)(pkt->pts - pkt->dts);
|
||||
|
||||
Reference in New Issue
Block a user