From e0d2cacf9c963433052bc74c6573b97c3a211d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sat, 20 Sep 2008 06:24:43 +0000 Subject: [PATCH] Make timestamps continious even if we skip over commercial breaks during recording. --- dvr/dvr.h | 7 +++++++ dvr/dvr_rec.c | 37 +++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/dvr/dvr.h b/dvr/dvr.h index 5af60e53..52b50792 100644 --- a/dvr/dvr.h +++ b/dvr/dvr.h @@ -88,6 +88,13 @@ typedef struct dvr_entry { /** * Initialized upon SUBSCRIPTION_TRANSPORT_RUN */ + int64_t de_ts_offset; /* Offset to compensate for PTS/DTS not beeing + 0 at start of recording */ + + int64_t de_ts_com_start; /* Starttime for last/current commercial break */ + int64_t de_ts_com_offset; /* Offset to subtract to PTS/DTS to skip over + all commercial breaks so far */ + struct dvr_rec_stream_list de_streams; streaming_target_t de_st; AVFormatContext *de_fctx; diff --git a/dvr/dvr_rec.c b/dvr/dvr_rec.c index 85f8522a..a9b014f2 100644 --- a/dvr/dvr_rec.c +++ b/dvr/dvr_rec.c @@ -339,7 +339,8 @@ dvr_rec_start(dvr_entry_t *de, streaming_pad_t *sp) streaming_target_init(&de->de_st); streaming_target_connect(sp, &de->de_st); de->de_st.st_status = ST_RUNNING; - de->de_fctx = fctx;+ + de->de_fctx = fctx; + de->de_ts_offset = AV_NOPTS_VALUE; pthread_mutex_unlock(sp->sp_mutex); @@ -468,6 +469,7 @@ dvr_thread_new_pkt(dvr_entry_t *de, th_pkt_t *pkt) void *buf = pkt->pkt_payload; size_t bufsize = pkt->pkt_payloadlen; char txt[100]; + int64_t pts, dts; LIST_FOREACH(drs, &de->de_streams, drs_link) if(drs->drs_source_index == pkt->pkt_componentindex) @@ -479,6 +481,9 @@ dvr_thread_new_pkt(dvr_entry_t *de, th_pkt_t *pkt) st = drs->drs_lavf_stream; ctx = st->codec; + if(de->de_ts_offset == AV_NOPTS_VALUE) + de->de_ts_offset = pkt->pkt_dts; + switch(de->de_rec_state) { default: break; @@ -563,16 +568,26 @@ dvr_thread_new_pkt(dvr_entry_t *de, th_pkt_t *pkt) if(de->de_header_written == 0) break; - if(pkt->pkt_commercial == COMMERCIAL_YES) { + if(pkt->pkt_commercial == COMMERCIAL_YES && + st->codec->codec->type == CODEC_TYPE_VIDEO && + pkt->pkt_frametype == PKT_I_FRAME) { + + de->de_ts_com_start = pkt->pkt_dts; + de->de_rec_state = DE_RS_COMMERCIAL; break; } + outputpacket: + dts = pkt->pkt_dts - de->de_ts_offset - de->de_ts_com_offset; + pts = pkt->pkt_pts - de->de_ts_offset - de->de_ts_com_offset; + if(dts < 0 || pts < 0) + break; av_init_packet(&avpkt); avpkt.stream_index = st->index; - avpkt.dts = av_rescale_q(pkt->pkt_dts, AV_TIME_BASE_Q, st->time_base); - avpkt.pts = av_rescale_q(pkt->pkt_pts, AV_TIME_BASE_Q, st->time_base); + avpkt.dts = av_rescale_q(dts, AV_TIME_BASE_Q, st->time_base); + avpkt.pts = av_rescale_q(pts, AV_TIME_BASE_Q, st->time_base); avpkt.data = buf; avpkt.size = bufsize; avpkt.duration = @@ -584,12 +599,18 @@ dvr_thread_new_pkt(dvr_entry_t *de, th_pkt_t *pkt) case DE_RS_COMMERCIAL: - if(pkt->pkt_commercial != COMMERCIAL_YES) { + if(pkt->pkt_commercial != COMMERCIAL_YES && + st->codec->codec->type == CODEC_TYPE_VIDEO && + pkt->pkt_frametype == PKT_I_FRAME) { - LIST_FOREACH(drs, &de->de_streams, drs_link) - drs->drs_decoded = 0; + /* Switch out of commercial mode */ - de->de_rec_state = DE_RS_WAIT_AUDIO_LOCK; + de->de_ts_com_offset += (pkt->pkt_dts - de->de_ts_com_start); + de->de_rec_state = DE_RS_RUNNING; + + tvhlog(LOG_ERR, "dvr", "%s - Skipped %lld seconds of commercials", + de->de_title, (pkt->pkt_dts - de->de_ts_com_start) / 1000000); + goto outputpacket; } break; }