Changeset 49dbed5be in mythtv
- Timestamp:
- Jan 1, 2013, 3:23:42 AM (12 years ago)
- Branches:
- devel/2020-player, devel/ffmpeg-resync, fixes/0.27, fixes/0.28, fixes/29, fixes/30, fixes/31, github-templates, master
- Children:
- 88573b7466
- Parents:
- 1eaecea6dd
- Location:
- mythtv
- Files:
-
- 33 edited
-
bindings/perl/MythTV.pm (modified) (1 diff)
-
bindings/php/MythBackend.php (modified) (1 diff)
-
bindings/python/MythTV/static.py (modified) (2 diffs)
-
libs/libmythbase/mythversion.h (modified) (2 diffs)
-
libs/libmythtv/DVD/mythdvdplayer.cpp (modified) (1 diff)
-
libs/libmythtv/DVD/mythdvdplayer.h (modified) (1 diff)
-
libs/libmythtv/avformatdecoder.cpp (modified) (1 diff)
-
libs/libmythtv/decoderbase.cpp (modified) (8 diffs)
-
libs/libmythtv/decoderbase.h (modified) (2 diffs)
-
libs/libmythtv/deletemap.cpp (modified) (39 diffs)
-
libs/libmythtv/deletemap.h (modified) (5 diffs)
-
libs/libmythtv/mythcommflagplayer.cpp (modified) (1 diff)
-
libs/libmythtv/mythplayer.cpp (modified) (44 diffs)
-
libs/libmythtv/mythplayer.h (modified) (4 diffs)
-
libs/libmythtv/nuppeldecoder.cpp (modified) (2 diffs)
-
libs/libmythtv/recorders/dtvrecorder.cpp (modified) (12 diffs)
-
libs/libmythtv/recorders/dtvrecorder.h (modified) (2 diffs)
-
libs/libmythtv/recorders/recorderbase.cpp (modified) (3 diffs)
-
libs/libmythtv/recorders/recorderbase.h (modified) (2 diffs)
-
libs/libmythtv/remoteencoder.cpp (modified) (2 diffs)
-
libs/libmythtv/remoteencoder.h (modified) (2 diffs)
-
libs/libmythtv/tv_play.cpp (modified) (7 diffs)
-
libs/libmythtv/tv_play.h (modified) (1 diff)
-
libs/libmythtv/tv_rec.cpp (modified) (1 diff)
-
libs/libmythtv/tv_rec.h (modified) (1 diff)
-
programs/mythbackend/encoderlink.cpp (modified) (1 diff)
-
programs/mythbackend/encoderlink.h (modified) (1 diff)
-
programs/mythbackend/mainserver.cpp (modified) (1 diff)
-
programs/mythtranscode/cutter.cpp (modified) (4 diffs)
-
programs/mythtranscode/cutter.h (modified) (1 diff)
-
programs/mythtranscode/main.cpp (modified) (2 diffs)
-
programs/mythtranscode/mpeg2fix.cpp (modified) (2 diffs)
-
programs/mythtranscode/transcode.cpp (modified) (2 diffs, 1 prop)
Legend:
- Unmodified
- Added
- Removed
-
mythtv/bindings/perl/MythTV.pm
r1eaecea6dd r49dbed5be 108 108 # versions of the form "58a". This will get used if protocol versions are 109 109 # changed on a fixes branch ongoing. 110 our $PROTO_VERSION = "7 6";111 our $PROTO_TOKEN = " FireWilde";110 our $PROTO_VERSION = "77"; 111 our $PROTO_TOKEN = "WindMark"; 112 112 113 113 # currentDatabaseVersion is defined in libmythtv in -
mythtv/bindings/php/MythBackend.php
r1eaecea6dd r49dbed5be 12 12 // MYTH_PROTO_VERSION is defined in libmyth in mythtv/libs/libmyth/mythcontext.h 13 13 // and should be the current MythTV protocol version. 14 static $protocol_version = '7 6';15 static $protocol_token = ' FireWilde';14 static $protocol_version = '77'; 15 static $protocol_token = 'WindMark'; 16 16 17 17 // The character string used by the backend to separate records -
mythtv/bindings/python/MythTV/static.py
r1eaecea6dd r49dbed5be 9 9 NVSCHEMA_VERSION = 1007 10 10 MUSICSCHEMA_VERSION = 1018 11 PROTO_VERSION = '7 6'12 PROTO_TOKEN = ' FireWilde'11 PROTO_VERSION = '77' 12 PROTO_TOKEN = 'WindMark' 13 13 BACKEND_SEP = '[]:[]' 14 14 INSTALL_PREFIX = '/usr/local' … … 35 35 MARK_VIDEO_WIDTH = 30 36 36 MARK_VIDEO_HEIGHT = 31 37 MARK_VIDEO_RATE = 32 38 MARK_DURATION_MS = 33 37 39 38 40 class RECTYPE( object ): -
mythtv/libs/libmythbase/mythversion.h
r1eaecea6dd r49dbed5be 13 13 /// Including changes in the libmythbase, libmyth, libmythtv, libmythav* and 14 14 /// libmythui class methods used by plug-ins. 15 #define MYTH_BINARY_VERSION "0.27.201212 27-2"15 #define MYTH_BINARY_VERSION "0.27.20121231-1" 16 16 17 17 /** \brief Increment this whenever the MythTV network protocol changes. … … 35 35 * mythtv/bindings/python/MythTV/static.py (version number) 36 36 * mythtv/bindings/python/MythTV/mythproto.py (layout) 37 * 38 * Be kind and update the wiki as well. 39 * http://www.mythtv.org/wiki/Category:Myth_Protocol_Commands 40 * http://www.mythtv.org/wiki/Category:Myth_Protocol 37 41 */ 38 #define MYTH_PROTO_VERSION "7 6"39 #define MYTH_PROTO_TOKEN " FireWilde"42 #define MYTH_PROTO_VERSION "77" 43 #define MYTH_PROTO_TOKEN "WindMark" 40 44 41 45 /** \brief Increment this whenever the MythTV core database schema changes. -
mythtv/libs/libmythtv/DVD/mythdvdplayer.cpp
r1eaecea6dd r49dbed5be 391 391 } 392 392 393 int64_t MythDVDPlayer::GetSecondsPlayed(void)394 {395 if (!player_ctx->buffer->IsDVD())396 return 0;397 398 return (m_stillFrameLength > 0) ?399 (m_stillFrameTimer.elapsed() / 1000) :400 (player_ctx->buffer->DVD()->GetCurrentTime());401 402 }403 404 393 int64_t MythDVDPlayer::GetTotalSeconds(void) const 405 394 { -
mythtv/libs/libmythtv/DVD/mythdvdplayer.h
r1eaecea6dd r49dbed5be 20 20 // Gets 21 21 virtual uint64_t GetBookmark(void); 22 virtual int64_t GetSecondsPlayed(void);23 22 virtual int64_t GetTotalSeconds(void) const; 24 23 -
mythtv/libs/libmythtv/avformatdecoder.cpp
r1eaecea6dd r49dbed5be 2946 2946 2947 2947 QMutexLocker locker(&m_positionMapLock); 2948 // Create a dummy positionmap entry for frame 0 so that 2949 // seeking will work properly. (See 2950 // DecoderBase::FindPosition() which subtracts 2951 // DecoderBase::indexOffset from each frame number.) 2952 if (m_positionMap.empty()) 2953 { 2954 PosMapEntry dur = {0, 0, 0}; 2955 m_positionMap.push_back(dur); 2956 } 2948 2957 m_positionMap.push_back(entry); 2958 m_frameToDurMap[framesRead] = totalDuration / 1000; 2959 m_durToFrameMap[m_frameToDurMap[framesRead]] = framesRead; 2949 2960 } 2950 2961 -
mythtv/libs/libmythtv/decoderbase.cpp
r1eaecea6dd r49dbed5be 120 120 121 121 // Overwrites current positionmap with entire contents of database 122 frm_pos_map_t posMap ;122 frm_pos_map_t posMap, durMap; 123 123 124 124 if (ringBuffer && ringBuffer->IsDVD()) … … 192 192 return false; // no position map in recording 193 193 194 m_playbackinfo->QueryPositionMap(durMap, MARK_DURATION_MS); 195 194 196 QMutexLocker locker(&m_positionMapLock); 195 197 m_positionMap.clear(); … … 213 215 } 214 216 217 uint64_t last = 0; 218 for (frm_pos_map_t::const_iterator it = durMap.begin(); 219 it != durMap.end(); ++it) 220 { 221 m_frameToDurMap[it.key()] = it.value(); 222 m_durToFrameMap[it.value()] = it.key(); 223 last = it.key(); 224 } 225 226 if (!m_durToFrameMap.empty()) 227 { 228 LOG(VB_PLAYBACK, LOG_INFO, LOC + 229 QString("Duration map filled from DB to: %1").arg(last)); 230 } 231 215 232 return true; 216 233 } … … 236 253 } 237 254 238 QMap<long long, long long> posMap;239 if (!m_parent->PosMapFromEnc(start, posMap ))255 frm_pos_map_t posMap, durMap; 256 if (!m_parent->PosMapFromEnc(start, posMap, durMap)) 240 257 return false; 241 258 … … 244 261 // append this new position map to class's 245 262 m_positionMap.reserve(m_positionMap.size() + posMap.size()); 246 long longlast_index = m_positionMap.back().index;247 for ( QMap<long long,long long>::const_iterator it = posMap.begin();263 uint64_t last_index = m_positionMap.back().index; 264 for (frm_pos_map_t::const_iterator it = posMap.begin(); 248 265 it != posMap.end(); ++it) 249 266 { 250 267 if (it.key() <= last_index) 251 continue; // we released the m_positionMapLock for a few ms...268 continue; 252 269 253 270 PosMapEntry e = {it.key(), it.key() * keyframedist, *it}; … … 263 280 QString("Position map filled from Encoder to: %1") 264 281 .arg(m_positionMap.back().index)); 282 } 283 284 bool isEmpty = m_frameToDurMap.empty(); 285 if (!isEmpty) 286 { 287 frm_pos_map_t::const_iterator it = m_frameToDurMap.end(); 288 --it; 289 last_index = it.key(); 290 } 291 for (frm_pos_map_t::const_iterator it = durMap.begin(); 292 it != durMap.end(); ++it) 293 { 294 if (!isEmpty && it.key() <= last_index) 295 continue; // we released the m_positionMapLock for a few ms... 296 m_frameToDurMap[it.key()] = it.value(); 297 m_durToFrameMap[it.value()] = it.key(); 298 } 299 300 if (!m_frameToDurMap.empty()) 301 { 302 frm_pos_map_t::const_iterator it = m_frameToDurMap.end(); 303 --it; 304 LOG(VB_PLAYBACK, LOG_INFO, LOC + 305 QString("Duration map filled from Encoder to: %1").arg(it.key())); 265 306 } 266 307 … … 492 533 } 493 534 535 frm_pos_map_t durMap; 536 for (frm_pos_map_t::const_iterator it = m_frameToDurMap.begin(); 537 it != m_frameToDurMap.end(); ++it) 538 { 539 if (it.key() < first) 540 continue; 541 if (it.key() > last) 542 break; 543 durMap[it.key()] = it.value(); 544 } 545 494 546 locker.unlock(); 495 547 496 548 stm.start(); 497 549 m_playbackinfo->SavePositionMapDelta(posMap, type); 550 m_playbackinfo->SavePositionMapDelta(durMap, MARK_DURATION_MS); 498 551 499 552 #if 0 … … 1155 1208 } 1156 1209 1210 // Linearly interpolate the value for a given key in the map. If the 1211 // key is outside the range of keys in the map, linearly extrapolate 1212 // using the fallback ratio. 1213 uint64_t DecoderBase::TranslatePosition(const frm_pos_map_t &map, 1214 uint64_t key, 1215 float fallback_ratio) 1216 { 1217 uint64_t key1, key2; 1218 uint64_t val1, val2; 1219 1220 frm_pos_map_t::const_iterator lower = map.lowerBound(key); 1221 // QMap::lowerBound() finds a key >= the given key. We want one 1222 // <= the given key, so back up one element upon > condition. 1223 if (lower != map.begin() && (lower == map.end() || lower.key() > key)) 1224 --lower; 1225 if (lower == map.end()) 1226 { 1227 key1 = 0; 1228 val1 = 0; 1229 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + 1230 QString("TranslatePosition(key=%1): extrapolating to (0,0)") 1231 .arg(key)); 1232 } 1233 else 1234 { 1235 key1 = lower.key(); 1236 val1 = lower.value(); 1237 } 1238 // Find the next key >= the given key. QMap::lowerBound() is 1239 // precisely correct in this case. 1240 frm_pos_map_t::const_iterator upper = map.lowerBound(key); 1241 if (upper == map.end()) 1242 { 1243 // Extrapolate from (key1,val1) based on fallback_ratio 1244 key2 = key; 1245 val2 = val1 + fallback_ratio * (key2 - key1) + 0.5; 1246 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + 1247 QString("TranslatePosition(key=%1, ratio=%2): " 1248 "extrapolating to (%3,%4)") 1249 .arg(key).arg(fallback_ratio).arg(key2).arg(val2)); 1250 return val2; 1251 } 1252 else 1253 { 1254 key2 = upper.key(); 1255 val2 = upper.value(); 1256 } 1257 if (key1 == key2) // this happens for an exact keyframe match 1258 return val2; // can also set key2 = key1 + 1 avoid dividing by zero 1259 1260 return val1 + (double) (key - key1) * (val2 - val1) / (key2 - key1) + 0.5; 1261 } 1262 1263 // Convert from an absolute frame number (not cutlist adjusted) to its 1264 // cutlist-adjusted position in milliseconds. 1265 uint64_t DecoderBase::TranslatePositionFrameToMs(uint64_t position, 1266 float fallback_framerate, 1267 const frm_dir_map_t &cutlist) 1268 const 1269 { 1270 QMutexLocker locker(&m_positionMapLock); 1271 return TranslatePositionAbsToRel(cutlist, position, m_frameToDurMap, 1272 1000 / fallback_framerate); 1273 } 1274 1275 // Convert from a cutlist-adjusted position in milliseconds to its 1276 // absolute frame number (not cutlist-adjusted). 1277 uint64_t DecoderBase::TranslatePositionMsToFrame(uint64_t dur_ms, 1278 float fallback_framerate, 1279 const frm_dir_map_t &cutlist) 1280 const 1281 { 1282 QMutexLocker locker(&m_positionMapLock); 1283 // Convert relative position in milliseconds (cutlist-adjusted) to 1284 // its absolute position in milliseconds (not cutlist-adjusted). 1285 uint64_t ms = TranslatePositionRelToAbs(cutlist, dur_ms, m_frameToDurMap, 1286 1000 / fallback_framerate); 1287 // Convert absolute position in milliseconds to its absolute frame 1288 // number. 1289 return TranslatePosition(m_durToFrameMap, ms, fallback_framerate / 1000); 1290 } 1291 1292 // Convert from an "absolute" (not cutlist-adjusted) value to its 1293 // "relative" (cutlist-adjusted) mapped value. Usually the position 1294 // argument is a frame number, the map argument maps frames to 1295 // milliseconds, the fallback_ratio is 1000/framerate_fps, and the 1296 // return value is in milliseconds. 1297 // 1298 // If the map and fallback_ratio arguments are omitted, it simply 1299 // converts from an absolute frame number to a relative 1300 // (cutlist-adjusted) frame number. 1301 uint64_t 1302 DecoderBase::TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap, 1303 uint64_t absPosition, // frames 1304 const frm_pos_map_t &map, // frame->ms 1305 float fallback_ratio) 1306 { 1307 uint64_t subtraction = 0; 1308 uint64_t startOfCutRegion = 0; 1309 bool withinCut = false; 1310 bool first = true; 1311 for (frm_dir_map_t::const_iterator i = deleteMap.begin(); 1312 i != deleteMap.end(); ++i) 1313 { 1314 if (first) 1315 withinCut = (i.value() == MARK_CUT_END); 1316 first = false; 1317 if (i.key() > absPosition) 1318 break; 1319 uint64_t mappedKey = TranslatePosition(map, i.key(), fallback_ratio); 1320 if (i.value() == MARK_CUT_START && !withinCut) 1321 { 1322 withinCut = true; 1323 startOfCutRegion = mappedKey; 1324 } 1325 else if (i.value() == MARK_CUT_END && withinCut) 1326 { 1327 withinCut = false; 1328 subtraction += (mappedKey - startOfCutRegion); 1329 } 1330 } 1331 uint64_t mappedPos = TranslatePosition(map, absPosition, fallback_ratio); 1332 if (withinCut) 1333 subtraction += (mappedPos - startOfCutRegion); 1334 return mappedPos - subtraction; 1335 } 1336 1337 // Convert from a "relative" (cutlist-adjusted) value to its 1338 // "absolute" (not cutlist-adjusted) mapped value. Usually the 1339 // position argument is in milliseconds, the map argument maps frames 1340 // to milliseconds, the fallback_ratio is 1000/framerate_fps, and the 1341 // return value is also in milliseconds. Upon return, if necessary, 1342 // the result may need a separate, non-cutlist adjusted conversion 1343 // from milliseconds to frame number, using the inverse 1344 // millisecond-to-frame map and the inverse fallback_ratio; see for 1345 // example TranslatePositionMsToFrame(). 1346 // 1347 // If the map and fallback_ratio arguments are omitted, it simply 1348 // converts from a relatve (cutlist-adjusted) frame number to an 1349 // absolute frame number. 1350 uint64_t 1351 DecoderBase::TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap, 1352 uint64_t relPosition, // ms 1353 const frm_pos_map_t &map, // frame->ms 1354 float fallback_ratio) 1355 { 1356 uint64_t addition = 0; 1357 uint64_t startOfCutRegion = 0; 1358 bool withinCut = false; 1359 bool first = true; 1360 for (frm_dir_map_t::const_iterator i = deleteMap.begin(); 1361 i != deleteMap.end(); ++i) 1362 { 1363 if (first) 1364 withinCut = (i.value() == MARK_CUT_END); 1365 first = false; 1366 uint64_t mappedKey = TranslatePosition(map, i.key(), fallback_ratio); 1367 if (i.value() == MARK_CUT_START && !withinCut) 1368 { 1369 withinCut = true; 1370 startOfCutRegion = mappedKey; 1371 if (relPosition + addition <= startOfCutRegion) 1372 break; 1373 } 1374 else if (i.value() == MARK_CUT_END && withinCut) 1375 { 1376 withinCut = false; 1377 addition += (mappedKey - startOfCutRegion); 1378 } 1379 } 1380 return relPosition + addition; 1381 } 1382 1157 1383 1158 1384 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
mythtv/libs/libmythtv/decoderbase.h
r1eaecea6dd r49dbed5be 142 142 virtual bool DoFastForward(long long desiredFrame, bool doflush = true); 143 143 144 static uint64_t 145 TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap, 146 uint64_t absPosition, 147 const frm_pos_map_t &map = frm_pos_map_t(), 148 float fallback_ratio = 1.0); 149 static uint64_t 150 TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap, 151 uint64_t relPosition, 152 const frm_pos_map_t &map = frm_pos_map_t(), 153 float fallback_ratio = 1.0); 154 static uint64_t TranslatePosition(const frm_pos_map_t &map, 155 uint64_t key, 156 float fallback_ratio); 157 uint64_t TranslatePositionFrameToMs(uint64_t position, 158 float fallback_framerate, 159 const frm_dir_map_t &cutlist) const; 160 uint64_t TranslatePositionMsToFrame(uint64_t dur_ms, 161 float fallback_framerate, 162 const frm_dir_map_t &cutlist) const; 163 144 164 float GetVideoAspect(void) const { return current_aspect; } 145 165 … … 275 295 mutable QMutex m_positionMapLock; 276 296 vector<PosMapEntry> m_positionMap; 297 frm_pos_map_t m_frameToDurMap; // guarded by m_positionMapLock 298 frm_pos_map_t m_durToFrameMap; // guarded by m_positionMapLock 277 299 bool dontSyncPositionMap; 278 300 -
mythtv/libs/libmythtv/deletemap.cpp
r1eaecea6dd r49dbed5be 34 34 m_undoStack.append(entry); 35 35 m_undoStackPointer ++; 36 SaveMap( 0,true);36 SaveMap(true); 37 37 } 38 38 … … 44 44 m_deleteMap = m_undoStack[m_undoStackPointer].deleteMap; 45 45 m_changed = true; 46 SaveMap( 0,true);46 SaveMap(true); 47 47 return true; 48 48 } … … 55 55 m_deleteMap = m_undoStack[m_undoStackPointer].deleteMap; 56 56 m_changed = true; 57 SaveMap( 0,true);57 SaveMap(true); 58 58 return true; 59 59 } … … 71 71 } 72 72 73 bool DeleteMap::HandleAction(QString &action, uint64_t frame, 74 uint64_t played, uint64_t total, double rate) 73 bool DeleteMap::HandleAction(QString &action, uint64_t frame, uint64_t played) 75 74 { 76 75 bool handled = true; 77 76 if (action == ACTION_UP) 78 UpdateSeekAmount(1 , rate);77 UpdateSeekAmount(1); 79 78 else if (action == ACTION_DOWN) 80 UpdateSeekAmount(-1 , rate);79 UpdateSeekAmount(-1); 81 80 else if (action == ACTION_CLEARMAP) 82 81 Clear(tr("Clear Cuts")); 83 82 else if (action == ACTION_INVERTMAP) 84 ReverseAll( total);83 ReverseAll(); 85 84 else if (action == "MOVEPREV") 86 MoveRelative(frame, total,false);85 MoveRelative(frame, false); 87 86 else if (action == "MOVENEXT") 88 MoveRelative(frame, t otal, true);87 MoveRelative(frame, true); 89 88 else if (action == "CUTTOBEGINNING") 90 Add(frame, total,MARK_CUT_END, tr("Cut to Beginning"));89 Add(frame, MARK_CUT_END, tr("Cut to Beginning")); 91 90 else if (action == "CUTTOEND") 92 91 { 93 Add(frame, total,MARK_CUT_START, tr("Cut to End"));92 Add(frame, MARK_CUT_START, tr("Cut to End")); 94 93 // If the recording is still in progress, add an explicit end 95 94 // mark at the end. 96 95 if (m_ctx->player && m_ctx->player->IsWatchingInprogress()) 97 Add( total - 1, total, MARK_CUT_END, "");96 Add(m_ctx->player->GetTotalFrameCount() - 1, MARK_CUT_END, ""); 98 97 } 99 98 else if (action == "NEWCUT") 100 NewCut(frame , total);99 NewCut(frame); 101 100 else if (action == "DELETE") 102 101 //: Delete the current cut or preserved region 103 Delete(frame, t otal, tr("Delete"));102 Delete(frame, tr("Delete")); 104 103 else if (action == "UNDO") 105 104 Undo(); … … 111 110 } 112 111 113 void DeleteMap::UpdateSeekAmount(int change , double framerate)112 void DeleteMap::UpdateSeekAmount(int change) 114 113 { 115 114 m_seekamountpos += change; … … 124 123 case 0: m_seekText = tr("cut point"); m_seekamount = -2; break; 125 124 case 1: m_seekText = tr("keyframe"); m_seekamount = -1; break; 126 case 2: m_seekText = tr("1 frame"); m_seekamount = 1; break; 127 case 3: m_seekText = tr("0.5 seconds"); m_seekamount = (int)roundf(framerate / 2); break; 128 case 4: m_seekText = tr("%n second(s)", "", 1); m_seekamount = (int)roundf(framerate); break; 129 case 5: m_seekText = tr("%n second(s)", "", 5); m_seekamount = (int)roundf(framerate * 5); break; 130 case 6: m_seekText = tr("%n second(s)", "", 20); m_seekamount = (int)roundf(framerate * 20); break; 131 case 7: m_seekText = tr("%n minute(s)", "", 1); m_seekamount = (int)roundf(framerate * 60); break; 132 case 8: m_seekText = tr("%n minute(s)", "", 5); m_seekamount = (int)roundf(framerate * 300); break; 133 case 9: m_seekText = tr("%n minute(s)", "", 10); m_seekamount = (int)roundf(framerate * 600); break; 134 default: m_seekText = tr("error"); m_seekamount = (int)roundf(framerate); break; 135 } 136 } 137 138 static QString createTimeString(uint64_t frame, uint64_t total, 139 double frame_rate, bool full_resolution) 140 { 141 int secs = (int)(frame / frame_rate); 142 int frames = frame - (int)(secs * frame_rate); 143 int totalSecs = (int)(total / frame_rate); 125 case 2: m_seekText = tr("1 frame"); m_seekamount = 0; break; 126 case 3: m_seekText = tr("0.5 seconds"); m_seekamount = 0.5; break; 127 case 4: m_seekText = tr("%n second(s)", "", 1); m_seekamount = 1; break; 128 case 5: m_seekText = tr("%n second(s)", "", 5); m_seekamount = 5; break; 129 case 6: m_seekText = tr("%n second(s)", "", 20); m_seekamount = 20; break; 130 case 7: m_seekText = tr("%n minute(s)", "", 1); m_seekamount = 60; break; 131 case 8: m_seekText = tr("%n minute(s)", "", 5); m_seekamount = 300; break; 132 case 9: m_seekText = tr("%n minute(s)", "", 10); m_seekamount = 600; break; 133 default: m_seekText = tr("error"); m_seekamount = 1; break; 134 } 135 } 136 137 QString DeleteMap::CreateTimeString(uint64_t frame, bool use_cutlist, 138 double frame_rate, bool full_resolution) 139 const 140 { 141 uint64_t ms = TranslatePositionFrameToMs(frame, frame_rate, use_cutlist); 142 int secs = (int)(ms / 1000); 143 int remainder = (int)(ms % 1000); 144 int totalSecs = (int) 145 (TranslatePositionFrameToMs(frame, frame_rate, use_cutlist) / 1000); 144 146 QString timestr; 145 147 if (totalSecs >= 3600) … … 148 150 QString(":%1").arg(secs % 60, 2, 10, QChar(48)); 149 151 if (full_resolution) 150 timestr += QString(".%1").arg( frames, 2, 10, QChar(48));152 timestr += QString(".%1").arg(remainder, 3, 10, QChar(48)); 151 153 return timestr; 152 154 } … … 156 158 * are only refreshed if the deleteMap has been updated. 157 159 */ 158 void DeleteMap::UpdateOSD(uint64_t frame, uint64_t total, double frame_rate, 159 OSD *osd) 160 void DeleteMap::UpdateOSD(uint64_t frame, double frame_rate, OSD *osd) 160 161 { 161 162 if (!osd || !m_ctx) 162 163 return; 163 CleanMap( total);164 CleanMap(); 164 165 165 166 InfoMap infoMap; … … 174 175 cutmarker = tr("cut"); 175 176 176 QString timestr = createTimeString(frame, total, frame_rate, true);177 uint64_t relTotal = TranslatePositionAbsToRel(total);178 QString relTimeDisplay = createTimeString(TranslatePositionAbsToRel(frame),179 relTotal, frame_rate, false);180 QString relLengthDisplay = createTimeString(relTotal,181 relTotal, frame_rate, false);177 uint64_t total = m_ctx->player->GetTotalFrameCount(); 178 QString timestr = CreateTimeString(frame, false, frame_rate, true); 179 QString relTimeDisplay; 180 relTimeDisplay = CreateTimeString(frame, true, frame_rate, false); 181 QString relLengthDisplay; 182 relLengthDisplay = CreateTimeString(total, true, frame_rate, false); 182 183 infoMap["timedisplay"] = timestr; 183 184 infoMap["framedisplay"] = QString::number(frame); … … 250 251 251 252 /// Reverses the direction of each mark in the map. 252 void DeleteMap::ReverseAll( uint64_t total)253 void DeleteMap::ReverseAll(void) 253 254 { 254 255 EDIT_CHECK; … … 257 258 Add(it.key(), it.value() == MARK_CUT_END ? MARK_CUT_START : 258 259 MARK_CUT_END); 259 CleanMap( total);260 CleanMap(); 260 261 Push(tr("Reverse Cuts")); 261 262 } … … 266 267 * the cleanup code. 267 268 */ 268 void DeleteMap::Add(uint64_t frame, uint64_t total, MarkTypes type, 269 QString undoMessage) 269 void DeleteMap::Add(uint64_t frame, MarkTypes type, QString undoMessage) 270 270 { 271 271 EDIT_CHECK; … … 281 281 // Delete the temporary mark before putting a real mark at its 282 282 // location 283 Delete(frame, total);283 Delete(frame, ""); 284 284 } 285 285 else // Don't add a mark on top of a mark … … 335 335 Delete((uint64_t)remove); 336 336 Add(frame, type); 337 CleanMap( total);337 CleanMap(); 338 338 if (!undoMessage.isEmpty()) 339 339 Push(undoMessage); … … 341 341 342 342 /// Remove the mark at the given frame. 343 void DeleteMap::Delete(uint64_t frame, uint64_t total,QString undoMessage)343 void DeleteMap::Delete(uint64_t frame, QString undoMessage) 344 344 { 345 345 EDIT_CHECK; … … 347 347 return; 348 348 349 uint64_t prev = GetNearestMark(frame, total,false);350 uint64_t next = GetNearestMark(frame, t otal, true);349 uint64_t prev = GetNearestMark(frame, false); 350 uint64_t next = GetNearestMark(frame, true); 351 351 352 352 // If frame is a cut point, GetNearestMark() would return the previous/next … … 367 367 if (prev != next) 368 368 Delete(next); 369 CleanMap( total);369 CleanMap(); 370 370 if (!undoMessage.isEmpty()) 371 371 Push(undoMessage); … … 373 373 374 374 /// Add a new cut marker (to start or end a cut region) 375 void DeleteMap::NewCut(uint64_t frame , uint64_t total)375 void DeleteMap::NewCut(uint64_t frame) 376 376 { 377 377 EDIT_CHECK; … … 391 391 if (existing > -1) 392 392 { 393 uint64_t total = m_ctx->player->GetTotalFrameCount(); 393 394 uint64_t otherframe = static_cast<uint64_t>(existing); 394 395 if (otherframe == frame) … … 403 404 { 404 405 MarkTypes type = MARK_UNSET; 405 cut_start = GetNearestMark(frame, total,false);406 cut_end = GetNearestMark(frame, t otal, true);406 cut_start = GetNearestMark(frame, false); 407 cut_end = GetNearestMark(frame, true); 407 408 frm_dir_map_t::Iterator it = m_deleteMap.find(frame); 408 409 if (it != m_deleteMap.end()) … … 467 468 Add(frame, MARK_PLACEHOLDER); 468 469 469 CleanMap( total);470 CleanMap(); 470 471 Push(tr("New Cut")); 471 472 } 472 473 473 474 /// Move the previous (!right) or next (right) cut to frame. 474 void DeleteMap::MoveRelative(uint64_t frame, uint64_t total,bool right)475 void DeleteMap::MoveRelative(uint64_t frame, bool right) 475 476 { 476 477 frm_dir_map_t::Iterator it = m_deleteMap.find(frame); … … 491 492 // instead, delete the region 492 493 //: Delete the current cut or preserved region 493 Delete(frame, t otal, tr("Delete"));494 Delete(frame, tr("Delete")); 494 495 return; 495 496 } … … 498 499 // Delete the temporary mark before putting a real mark at its 499 500 // location 500 Delete(frame, total);501 } 502 } 503 504 uint64_t from = GetNearestMark(frame, total,right);505 Move(from, frame , total);501 Delete(frame, ""); 502 } 503 } 504 505 uint64_t from = GetNearestMark(frame, right); 506 Move(from, frame); 506 507 } 507 508 508 509 /// Move an existing mark to a new frame. 509 void DeleteMap::Move(uint64_t frame, uint64_t to , uint64_t total)510 void DeleteMap::Move(uint64_t frame, uint64_t to) 510 511 { 511 512 EDIT_CHECK; … … 515 516 if (frame == 0) 516 517 type = MARK_CUT_START; 517 else if (frame == total)518 else if (frame == m_ctx->player->GetTotalFrameCount()) 518 519 type = MARK_CUT_END; 519 520 } 520 Add(to, t otal, type, tr("Move Mark"));521 Add(to, type, tr("Move Mark")); 521 522 } 522 523 … … 585 586 * next/previous mark exists, and false otherwise. 586 587 */ 587 uint64_t DeleteMap::GetNearestMark( 588 uint64_t frame, uint64_t total, bool right, 589 bool *hasMark) const 588 uint64_t DeleteMap::GetNearestMark(uint64_t frame, bool right, bool *hasMark) 589 const 590 590 { 591 591 uint64_t result; … … 595 595 if (right) 596 596 { 597 result = total;597 result = m_ctx->player->GetTotalFrameCount(); 598 598 for (; it != m_deleteMap.end(); ++it) 599 599 if (it.key() > frame) … … 636 636 * not include the first or last frames. 637 637 */ 638 void DeleteMap::CleanMap( uint64_t total)638 void DeleteMap::CleanMap(void) 639 639 { 640 640 if (IsEmpty()) 641 641 return; 642 642 643 uint64_t total = m_ctx->player->GetTotalFrameCount(); 643 644 Delete(0); 644 645 Delete(total); … … 694 695 695 696 /// Loads the given commercial break map into the deleteMap. 696 void DeleteMap::LoadCommBreakMap( uint64_t total,frm_dir_map_t &map)697 void DeleteMap::LoadCommBreakMap(frm_dir_map_t &map) 697 698 { 698 699 Clear(); … … 701 702 Add(it.key(), it.value() == MARK_COMM_START ? 702 703 MARK_CUT_START : MARK_CUT_END); 703 CleanMap( total);704 CleanMap(); 704 705 Push(tr("Load Detected Commercials")); 705 706 } 706 707 707 708 /// Loads the delete map from the database. 708 void DeleteMap::LoadMap( uint64_t total,QString undoMessage)709 void DeleteMap::LoadMap(QString undoMessage) 709 710 { 710 711 if (!m_ctx || !m_ctx->playingInfo || gCoreContext->IsDatabaseIgnored()) … … 715 716 m_ctx->playingInfo->QueryCutList(m_deleteMap); 716 717 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__); 717 CleanMap( total);718 CleanMap(); 718 719 if (!undoMessage.isEmpty()) 719 720 Push(undoMessage); … … 722 723 /// Returns true if an auto-save map was loaded. 723 724 /// Does nothing and returns false if not. 724 bool DeleteMap::LoadAutoSaveMap( uint64_t total)725 bool DeleteMap::LoadAutoSaveMap(void) 725 726 { 726 727 if (!m_ctx || !m_ctx->playingInfo || gCoreContext->IsDatabaseIgnored()) … … 732 733 bool result = m_ctx->playingInfo->QueryCutList(m_deleteMap, true); 733 734 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__); 734 CleanMap( total);735 CleanMap(); 735 736 if (result) 736 737 Push(tr("Load Auto-saved Cuts")); … … 742 743 743 744 /// Saves the delete map to the database. 744 void DeleteMap::SaveMap( uint64_t total,bool isAutoSave)745 void DeleteMap::SaveMap(bool isAutoSave) 745 746 { 746 747 if (!m_ctx || !m_ctx->playingInfo || gCoreContext->IsDatabaseIgnored()) … … 761 762 } 762 763 763 CleanMap( total);764 CleanMap(); 764 765 } 765 766 m_ctx->LockPlayingInfo(__FILE__, __LINE__); … … 775 776 * many times per second. 776 777 */ 777 void DeleteMap::TrackerReset(uint64_t frame , uint64_t total)778 void DeleteMap::TrackerReset(uint64_t frame) 778 779 { 779 780 m_nextCutStart = 0; … … 794 795 ++cutpoint; 795 796 m_nextCutStartIsValid = (cutpoint != m_deleteMap.end()); 796 m_nextCutStart = m_nextCutStartIsValid ? cutpoint.key() : total; 797 m_nextCutStart = m_nextCutStartIsValid ? cutpoint.key() : 798 m_ctx->player->GetTotalFrameCount(); 797 799 } 798 800 } 799 801 else 800 m_nextCutStart = GetNearestMark(frame, total,!IsInDelete(frame),802 m_nextCutStart = GetNearestMark(frame, !IsInDelete(frame), 801 803 &m_nextCutStartIsValid); 802 804 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Tracker next CUT_START: %1") … … 808 810 * and provides the frame number of the next jump. 809 811 */ 810 bool DeleteMap::TrackerWantsToJump(uint64_t frame, uint64_t total, uint64_t&to)812 bool DeleteMap::TrackerWantsToJump(uint64_t frame, uint64_t &to) 811 813 { 812 814 if (IsEmpty() || !m_nextCutStartIsValid || frame < m_nextCutStart) 813 815 return false; 814 816 815 to = GetNearestMark(m_nextCutStart, t otal, true);817 to = GetNearestMark(m_nextCutStart, true); 816 818 LOG(VB_PLAYBACK, LOG_INFO, LOC + 817 819 QString("Tracker wants to jump to: %1").arg(to)); … … 823 825 * cut sequence. 824 826 */ 825 uint64_t DeleteMap::GetLastFrame( uint64_t total) const826 { 827 uint64_t result = total;827 uint64_t DeleteMap::GetLastFrame(void) const 828 { 829 uint64_t result = m_ctx->player->GetTotalFrameCount(); 828 830 if (IsEmpty()) 829 831 return result; … … 863 865 } 864 866 865 uint64_t DeleteMap::TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap, 866 uint64_t absPosition) 867 { 868 uint64_t subtraction = 0; 869 uint64_t startOfCutRegion = 0; 870 frm_dir_map_t::const_iterator i; 871 bool withinCut = false; 872 bool first = true; 873 for (i = deleteMap.constBegin(); i != deleteMap.constEnd(); ++i) 874 { 875 if (first) 876 withinCut = (i.value() == MARK_CUT_END); 877 first = false; 878 if (i.key() > absPosition) 879 break; 880 if (i.value() == MARK_CUT_START && !withinCut) 881 { 882 withinCut = true; 883 startOfCutRegion = i.key(); 884 } 885 else if (i.value() == MARK_CUT_END && withinCut) 886 { 887 withinCut = false; 888 subtraction += (i.key() - startOfCutRegion); 889 } 890 } 891 if (withinCut) 892 subtraction += (absPosition - startOfCutRegion); 893 return absPosition - subtraction; 894 } 895 896 uint64_t DeleteMap::TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap, 897 uint64_t relPosition) 898 { 899 uint64_t addition = 0; 900 uint64_t startOfCutRegion = 0; 901 frm_dir_map_t::const_iterator i; 902 bool withinCut = false; 903 bool first = true; 904 for (i = deleteMap.constBegin(); i != deleteMap.constEnd(); ++i) 905 { 906 if (first) 907 withinCut = (i.value() == MARK_CUT_END); 908 first = false; 909 if (i.value() == MARK_CUT_START && !withinCut) 910 { 911 withinCut = true; 912 startOfCutRegion = i.key(); 913 if (relPosition + addition <= startOfCutRegion) 914 break; 915 } 916 else if (i.value() == MARK_CUT_END && withinCut) 917 { 918 withinCut = false; 919 addition += (i.key() - startOfCutRegion); 920 } 921 } 922 return relPosition + addition; 923 } 867 uint64_t DeleteMap::TranslatePositionFrameToMs(uint64_t position, 868 float fallback_framerate, 869 bool use_cutlist) const 870 { 871 return m_ctx->player->GetDecoder() 872 ->TranslatePositionFrameToMs(position, fallback_framerate, 873 use_cutlist ? m_deleteMap : 874 frm_dir_map_t()); 875 } 876 uint64_t DeleteMap::TranslatePositionMsToFrame(uint64_t dur_ms, 877 float fallback_framerate, 878 bool use_cutlist) const 879 { 880 return m_ctx->player->GetDecoder() 881 ->TranslatePositionMsToFrame(dur_ms, fallback_framerate, 882 use_cutlist ? m_deleteMap : 883 frm_dir_map_t()); 884 } 885 886 uint64_t DeleteMap::TranslatePositionAbsToRel(uint64_t position) const 887 { 888 return DecoderBase::TranslatePositionAbsToRel(m_deleteMap, position); 889 } 890 891 uint64_t DeleteMap::TranslatePositionRelToAbs(uint64_t position) const 892 { 893 return DecoderBase::TranslatePositionRelToAbs(m_deleteMap, position); 894 } -
mythtv/libs/libmythtv/deletemap.h
r1eaecea6dd r49dbed5be 26 26 m_nextCutStartIsValid(false), 27 27 m_nextCutStart(0), m_changed(true), 28 m_seekamountpos(4), m_seekamount( 30),29 m_ctx( 0), m_cachedTotalForOSD(0), m_undoStackPointer(-1)28 m_seekamountpos(4), m_seekamount(1.0), 29 m_ctx(NULL), m_cachedTotalForOSD(0), m_undoStackPointer(-1) 30 30 { 31 31 Push(""); … … 33 33 34 34 void SetPlayerContext(PlayerContext *ctx) { m_ctx = ctx; } 35 bool HandleAction(QString &action, uint64_t frame, uint64_t played, 36 uint64_t total, double rate); 37 int GetSeekAmount(void) const { return m_seekamount; } 38 void UpdateSeekAmount(int change, double framerate); 39 void SetSeekAmount(int amount) { m_seekamount = amount; } 35 bool HandleAction(QString &action, uint64_t frame, uint64_t played); 36 float GetSeekAmount(void) const { return m_seekamount; } 37 void UpdateSeekAmount(int change); 38 void SetSeekAmount(float amount) { m_seekamount = amount; } 40 39 41 void UpdateOSD(uint64_t frame, uint64_t total,double frame_rate, OSD *osd);40 void UpdateOSD(uint64_t frame, double frame_rate, OSD *osd); 42 41 43 42 bool IsEditing(void) const { return m_editing; } … … 49 48 50 49 void SetMap(const frm_dir_map_t &map); 51 void LoadCommBreakMap( uint64_t total,frm_dir_map_t &map);52 void SaveMap( uint64_t total,bool isAutoSave = false);53 void LoadMap( uint64_t total,QString undoMessage = "");54 bool LoadAutoSaveMap( uint64_t total);55 void CleanMap( uint64_t total);50 void LoadCommBreakMap(frm_dir_map_t &map); 51 void SaveMap(bool isAutoSave = false); 52 void LoadMap(QString undoMessage = ""); 53 bool LoadAutoSaveMap(void); 54 void CleanMap(void); 56 55 57 56 void Clear(QString undoMessage = ""); 58 void ReverseAll(uint64_t total); 59 void Add(uint64_t frame, uint64_t total, MarkTypes type, 60 QString undoMessage); 61 void NewCut(uint64_t frame, uint64_t total); 62 void Delete(uint64_t frame, uint64_t total, QString undoMessage = ""); 63 void MoveRelative(uint64_t frame, uint64_t total, bool right); 64 void Move(uint64_t frame, uint64_t to, uint64_t total); 57 void ReverseAll(void); 58 void Add(uint64_t frame, MarkTypes type, QString undoMessage); 59 void NewCut(uint64_t frame); 60 void Delete(uint64_t frame, QString undoMessage); 61 void MoveRelative(uint64_t frame, bool right); 62 void Move(uint64_t frame, uint64_t to); 65 63 66 64 bool IsInDelete(uint64_t frame) const; 67 uint64_t GetNearestMark(uint64_t frame, uint64_t total,bool right,68 bool *hasMark = 0) const;65 uint64_t GetNearestMark(uint64_t frame, bool right, 66 bool *hasMark = NULL) const; 69 67 bool IsTemporaryMark(uint64_t frame) const; 70 68 bool HasTemporaryMark(void) const; 71 uint64_t GetLastFrame(uint64_t total) const; 72 uint64_t TranslatePositionAbsToRel(uint64_t absPosition) const { 73 return TranslatePositionAbsToRel(m_deleteMap, absPosition); 74 } 75 uint64_t TranslatePositionRelToAbs(uint64_t relPosition) const { 76 return TranslatePositionRelToAbs(m_deleteMap, relPosition); 77 } 78 static uint64_t TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap, 79 uint64_t absPosition); 80 static uint64_t TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap, 81 uint64_t relPosition); 69 uint64_t GetLastFrame(void) const; 82 70 83 void TrackerReset(uint64_t frame, uint64_t total); 84 bool TrackerWantsToJump(uint64_t frame, uint64_t total, uint64_t &to); 71 // Provide translations between frame numbers and millisecond 72 // durations, optionally taking the custlist into account. 73 uint64_t TranslatePositionFrameToMs(uint64_t position, 74 float fallback_framerate, 75 bool use_cutlist) const; 76 uint64_t TranslatePositionMsToFrame(uint64_t dur_ms, 77 float fallback_framerate, 78 bool use_cutlist) const; 79 uint64_t TranslatePositionAbsToRel(uint64_t position) const; 80 uint64_t TranslatePositionRelToAbs(uint64_t position) const; 81 82 void TrackerReset(uint64_t frame); 83 bool TrackerWantsToJump(uint64_t frame, uint64_t &to); 85 84 86 85 bool Undo(void); … … 98 97 void Push(QString undoMessage); 99 98 99 QString CreateTimeString(uint64_t frame, bool use_cutlist, 100 double frame_rate, bool full_resolution) const; 101 100 102 bool m_editing; 101 103 bool m_nextCutStartIsValid; … … 105 107 bool m_changed; 106 108 int m_seekamountpos; 107 intm_seekamount;109 float m_seekamount; 108 110 PlayerContext *m_ctx; 109 111 uint64_t m_cachedTotalForOSD; -
mythtv/libs/libmythtv/mythcommflagplayer.cpp
r1eaecea6dd r49dbed5be 75 75 player_ctx->playingInfo->ClearPositionMap(MARK_GOP_START); 76 76 player_ctx->playingInfo->ClearPositionMap(MARK_GOP_BYFRAME); 77 player_ctx->playingInfo->ClearPositionMap(MARK_DURATION_MS); 77 78 } 78 79 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__); -
mythtv/libs/libmythtv/mythplayer.cpp
r1eaecea6dd r49dbed5be 16 16 #include <sys/time.h> 17 17 #include <assert.h> 18 #include <math.h> 18 19 19 20 // C++ headers … … 992 993 { 993 994 hasFullPositionMap = true; 994 deleteMap.LoadMap( totalFrames);995 deleteMap.TrackerReset(0 , totalFrames);995 deleteMap.LoadMap(); 996 deleteMap.TrackerReset(0); 996 997 } 997 998 998 999 // Determine the initial bookmark and update it for the cutlist 999 1000 bookmarkseek = GetBookmark(); 1000 deleteMap.TrackerReset(bookmarkseek , totalFrames);1001 deleteMap.TrackerWantsToJump(bookmarkseek, totalFrames,bookmarkseek);1001 deleteMap.TrackerReset(bookmarkseek); 1002 deleteMap.TrackerWantsToJump(bookmarkseek, bookmarkseek); 1002 1003 1003 1004 if (!gCoreContext->IsDatabaseIgnored() && … … 2396 2397 2397 2398 if (fftime <= 0) 2398 fftime = (long long)(seconds * video_frame_rate + 0.5); 2399 { 2400 float current = ComputeSecs(framesPlayed, true); 2401 float dest = current + seconds; 2402 uint64_t target = FindFrame(dest, true); 2403 fftime = target - framesPlayed; 2404 } 2399 2405 return fftime > CalcMaxFFTime(fftime, false); 2400 2406 } … … 2406 2412 2407 2413 if (rewindtime <= 0) 2408 rewindtime = (long long)(seconds * video_frame_rate + 0.5); 2414 { 2415 float current = ComputeSecs(framesPlayed, true); 2416 float dest = current + seconds; 2417 uint64_t target = FindFrame(dest, true); 2418 rewindtime = target - framesPlayed; 2419 } 2409 2420 return (uint64_t)rewindtime >= framesPlayed; 2410 2421 } … … 2767 2778 void MythPlayer::EventLoop(void) 2768 2779 { 2780 uint64_t frameCount = GetCurrentFrameCount(); 2769 2781 // recreate the osd if a reinit was triggered by another thread 2770 2782 if (reinit_osd) … … 2795 2807 forcePositionMapSync = true; 2796 2808 osdLock.lock(); 2797 deleteMap.UpdateOSD(framesPlayed, totalFrames, video_frame_rate, 2798 osd); 2809 deleteMap.UpdateOSD(framesPlayed, video_frame_rate, osd); 2799 2810 osdLock.unlock(); 2800 2811 editUpdateTimer.start(); … … 2943 2954 QString msg; 2944 2955 uint64_t jumpto = 0; 2956 // XXX CommBreakMap should use duration map not video_frame_rate 2945 2957 bool jump = commBreakMap.DoSkipCommercials(jumpto, framesPlayed, 2946 video_frame_rate, totalFrames, msg); 2958 video_frame_rate, 2959 frameCount, msg); 2947 2960 if (!msg.isEmpty()) 2948 2961 SetOSDStatus(msg, kOSDTimeout_Med); … … 2960 2973 { 2961 2974 QString msg; 2975 // XXX CommBreakMap should use duration map not video_frame_rate 2962 2976 bool jump = commBreakMap.AutoCommercialSkip(jumpto, framesPlayed, 2963 2977 video_frame_rate, 2964 totalFrames, msg);2978 frameCount, msg); 2965 2979 if (!msg.isEmpty()) 2966 2980 SetOSDStatus(msg, kOSDTimeout_Med); … … 2971 2985 // Handle cutlist skipping 2972 2986 if (!allpaused && (ffrew_skip == 1) && 2973 deleteMap.TrackerWantsToJump(framesPlayed, totalFrames,jumpto))2987 deleteMap.TrackerWantsToJump(framesPlayed, jumpto)) 2974 2988 { 2975 2989 if (jumpto == totalFrames) … … 3370 3384 } 3371 3385 3372 long long numFrames = totalFrames;3386 uint64_t numFrames = GetCurrentFrameCount(); 3373 3387 3374 3388 // For recordings we want to ignore the post-roll and account for … … 3552 3566 } 3553 3567 3568 bool MythPlayer::DoRewindSecs(float secs, double inaccuracy, bool use_cutlist) 3569 { 3570 float current = ComputeSecs(framesPlayed, use_cutlist); 3571 float target = current - secs; 3572 if (target < 0) 3573 target = 0; 3574 uint64_t targetFrame = FindFrame(target, use_cutlist); 3575 return DoRewind(framesPlayed - targetFrame, inaccuracy); 3576 } 3577 3554 3578 long long MythPlayer::CalcRWTime(long long rw) const 3555 3579 { … … 3560 3584 return rw; 3561 3585 3562 player_ctx->tvchain->JumpToNext(false, (int)(-15.0 * video_frame_rate)); 3586 player_ctx->tvchain->JumpToNext(false, (int)(-15.0 * video_frame_rate)); // XXX use seconds instead of assumed framerate 3563 3587 return -1; 3564 3588 } 3565 3589 3566 long long MythPlayer::CalcMaxFFTime(long long ff , bool setjump) const3567 { 3568 long long maxtime = (long long)(1.0 * video_frame_rate);3590 long long MythPlayer::CalcMaxFFTime(long long ffframes, bool setjump) const 3591 { 3592 float maxtime = 1.0; 3569 3593 bool islivetvcur = (livetv && player_ctx->tvchain && 3570 3594 !player_ctx->tvchain->HasNext()); 3571 3595 3572 3596 if (livetv || IsWatchingInprogress()) 3573 maxtime = (long long)(3.0 * video_frame_rate); 3574 3575 long long ret = ff; 3597 maxtime = 3.0; 3598 3599 long long ret = ffframes; 3600 float ff = ComputeSecs(ffframes, true); 3601 float secsPlayed = ComputeSecs(framesPlayed, true); 3576 3602 3577 3603 limitKeyRepeat = false; … … 3581 3607 if (totalFrames > 0) 3582 3608 { 3583 long long behind = totalFrames - framesPlayed;3609 float behind = ComputeSecs(totalFrames, true) - secsPlayed; 3584 3610 if (behind < maxtime || behind - ff <= maxtime * 2) 3585 3611 { … … 3592 3618 else if (islivetvcur || IsWatchingInprogress()) 3593 3619 { 3594 long long behind = player_ctx->recorder->GetFramesWritten() - 3595 framesPlayed; 3620 float secsWritten = 3621 ComputeSecs(player_ctx->recorder->GetFramesWritten(), true); 3622 float behind = secsWritten - secsPlayed; 3596 3623 3597 3624 if (behind < maxtime) // if we're close, do nothing 3598 3625 ret = 0; 3599 3626 else if (behind - ff <= maxtime) 3600 ret = behind - maxtime; 3627 ret = TranslatePositionMsToFrame(1000 * (secsWritten - maxtime), 3628 true) - framesPlayed; 3601 3629 3602 3630 if (behind < maxtime * 3) … … 3607 3635 if (totalFrames > 0) 3608 3636 { 3609 long long behind = totalFrames - framesPlayed;3637 float behind = ComputeSecs(totalFrames, true) - secsPlayed; 3610 3638 if (behind < maxtime) 3611 3639 ret = 0; 3612 3640 else if (behind - ff <= maxtime * 2) 3613 ret = behind - maxtime * 2; 3641 { 3642 uint64_t ms = 1000 * 3643 (ComputeSecs(totalFrames, true) - maxtime * 2); 3644 ret = TranslatePositionMsToFrame(ms, true) - framesPlayed; 3645 } 3614 3646 } 3615 3647 } … … 3660 3692 player_ctx->GetState() == kState_WatchingPreRecorded) 3661 3693 { 3662 if (framesRead >= deleteMap.GetLastFrame(totalFrames)) 3663 return true; 3664 framesLeft = (totalFrames > framesRead) ? totalFrames - framesRead : 0; 3694 uint64_t frameCount = GetCurrentFrameCount(); 3695 framesLeft = (frameCount > framesRead) ? frameCount - framesRead : 0; 3665 3696 return (framesLeft < (uint64_t)margin); 3666 3697 } … … 3695 3726 if (!deleteMap.IsEditing() && IsInDelete(desiredFrame)) 3696 3727 { 3697 uint64_t endcheck = deleteMap.GetLastFrame( totalFrames);3728 uint64_t endcheck = deleteMap.GetLastFrame(); 3698 3729 if (desiredFrame > endcheck) 3699 3730 desiredFrame = endcheck; … … 3709 3740 } 3710 3741 3742 bool MythPlayer::DoFastForwardSecs(float secs, double inaccuracy, 3743 bool use_cutlist) 3744 { 3745 float current = ComputeSecs(framesPlayed, use_cutlist); 3746 float target = current + secs; 3747 uint64_t targetFrame = FindFrame(target, use_cutlist); 3748 return DoFastForward(targetFrame - framesPlayed, inaccuracy); 3749 } 3750 3711 3751 void MythPlayer::DoJumpToFrame(uint64_t frame, double inaccuracy) 3712 3752 { … … 3727 3767 !player_ctx->tvchain->HasNext()); 3728 3768 3729 uint64_t max = totalFrames;3769 uint64_t max = GetCurrentFrameCount(); 3730 3770 if (islivetvcur || IsWatchingInprogress()) 3731 3771 { … … 3794 3834 audio.Reset(); 3795 3835 ResetCaptions(); 3796 deleteMap.TrackerReset(framesPlayed , totalFrames);3836 deleteMap.TrackerReset(framesPlayed); 3797 3837 commBreakMap.SetTracker(framesPlayed); 3798 3838 commBreakMap.ResetLastSkip(); … … 3835 3875 osd->HideAll(); 3836 3876 3837 bool loadedAutoSave = deleteMap.LoadAutoSaveMap( totalFrames);3877 bool loadedAutoSave = deleteMap.LoadAutoSaveMap(); 3838 3878 if (loadedAutoSave) 3839 3879 { … … 3842 3882 } 3843 3883 3844 deleteMap.UpdateSeekAmount(0 , video_frame_rate);3845 deleteMap.UpdateOSD(framesPlayed, totalFrames,video_frame_rate, osd);3884 deleteMap.UpdateSeekAmount(0); 3885 deleteMap.UpdateOSD(framesPlayed, video_frame_rate, osd); 3846 3886 deleteMap.SetFileEditing(true); 3847 3887 player_ctx->LockPlayingInfo(__FILE__, __LINE__); … … 3869 3909 deleteMap.SetEditing(false, osd); 3870 3910 if (howToSave == 0) 3871 deleteMap.LoadMap( totalFrames);3911 deleteMap.LoadMap(); 3872 3912 // Unconditionally save to remove temporary marks from the DB. 3873 3913 if (howToSave >= 0) 3874 deleteMap.SaveMap( totalFrames);3875 deleteMap.TrackerReset(framesPlayed , totalFrames);3914 deleteMap.SaveMap(); 3915 deleteMap.TrackerReset(framesPlayed); 3876 3916 deleteMap.SetFileEditing(false); 3877 3917 player_ctx->LockPlayingInfo(__FILE__, __LINE__); … … 3895 3935 QString action = actions[i]; 3896 3936 handled = true; 3897 int seekamount = deleteMap.GetSeekAmount();3937 float seekamount = deleteMap.GetSeekAmount(); 3898 3938 if (action == ACTION_LEFT) 3899 3939 { 3900 if (deleteMap.GetSeekAmount() > 0) 3901 { 3902 DoRewind(seekamount, seekamount > 1 ? 3903 kInaccuracyEditor : kInaccuracyNone); 3904 } 3940 if (seekamount == 0) // 1 frame 3941 DoRewind(1, kInaccuracyNone); 3942 else if (seekamount > 0) 3943 DoRewindSecs(seekamount, kInaccuracyEditor, false); 3905 3944 else 3906 3945 HandleArbSeek(false); … … 3908 3947 else if (action == ACTION_RIGHT) 3909 3948 { 3910 if (deleteMap.GetSeekAmount() > 0) 3911 { 3912 DoFastForward(seekamount, seekamount > 1 ? 3913 kInaccuracyEditor : kInaccuracyNone); 3914 } 3949 if (seekamount == 0) // 1 frame 3950 DoFastForward(1, kInaccuracyNone); 3951 else if (seekamount > 0) 3952 DoFastForwardSecs(seekamount, kInaccuracyEditor, false); 3915 3953 else 3916 3954 HandleArbSeek(true); … … 3922 3960 frm_dir_map_t map; 3923 3961 commBreakMap.GetMap(map); 3924 deleteMap.LoadCommBreakMap( totalFrames,map);3962 deleteMap.LoadCommBreakMap(map); 3925 3963 } 3926 3964 } 3927 3965 else if (action == ACTION_PREVCUT) 3928 3966 { 3929 int old_seekamount = deleteMap.GetSeekAmount();3967 float old_seekamount = deleteMap.GetSeekAmount(); 3930 3968 deleteMap.SetSeekAmount(-2); 3931 3969 HandleArbSeek(false); … … 3934 3972 else if (action == ACTION_NEXTCUT) 3935 3973 { 3936 int old_seekamount = deleteMap.GetSeekAmount();3974 float old_seekamount = deleteMap.GetSeekAmount(); 3937 3975 deleteMap.SetSeekAmount(-2); 3938 3976 HandleArbSeek(true); … … 3942 3980 else if (action == ACTION_BIGJUMPREW) 3943 3981 { 3944 if (seekamount > 0) 3945 DoRewind(seekamount * FFREW_MULTICOUNT, seekamount > 1 ? 3946 kInaccuracyEditor : kInaccuracyNone); 3982 if (seekamount == 0) 3983 DoRewind(FFREW_MULTICOUNT, kInaccuracyNone); 3984 else if (seekamount > 0) 3985 DoRewindSecs(seekamount * FFREW_MULTICOUNT, 3986 kInaccuracyEditor, false); 3947 3987 else 3948 { 3949 int fps = (int)ceil(video_frame_rate); 3950 DoRewind(fps * FFREW_MULTICOUNT / 2, kInaccuracyNone); 3951 } 3988 DoRewindSecs(FFREW_MULTICOUNT / 2, 3989 kInaccuracyNone, false); 3952 3990 } 3953 3991 else if (action == ACTION_BIGJUMPFWD) 3954 3992 { 3955 if (seekamount > 0) 3956 DoFastForward(seekamount * FFREW_MULTICOUNT, seekamount > 1 ? 3957 kInaccuracyEditor : kInaccuracyNone); 3993 if (seekamount == 0) 3994 DoFastForward(FFREW_MULTICOUNT, kInaccuracyNone); 3995 else if (seekamount > 0) 3996 DoFastForwardSecs(seekamount * FFREW_MULTICOUNT, 3997 kInaccuracyEditor, false); 3958 3998 else 3959 { 3960 int fps = (int)ceil(video_frame_rate); 3961 DoFastForward(fps * FFREW_MULTICOUNT / 2, 3962 kInaccuracyNone); 3963 } 3999 DoFastForwardSecs(FFREW_MULTICOUNT / 2, 4000 kInaccuracyNone, false); 3964 4001 } 3965 4002 else if (action == ACTION_SELECT) 3966 4003 { 3967 deleteMap.NewCut(frame , totalFrames);4004 deleteMap.NewCut(frame); 3968 4005 SetOSDMessage(tr("New cut added."), kOSDTimeout_Short); 3969 4006 refresh = true; … … 3971 4008 else if (action == "DELETE") 3972 4009 { 3973 deleteMap.Delete(frame, t otalFrames, tr("Delete"));4010 deleteMap.Delete(frame, tr("Delete")); 3974 4011 refresh = true; 3975 4012 } 3976 4013 else if (action == "REVERT") 3977 4014 { 3978 deleteMap.LoadMap(t otalFrames, tr("Undo Changes"));4015 deleteMap.LoadMap(tr("Undo Changes")); 3979 4016 refresh = true; 3980 4017 } … … 3986 4023 else if (action == ACTION_SAVEMAP) 3987 4024 { 3988 deleteMap.SaveMap( totalFrames);4025 deleteMap.SaveMap(); 3989 4026 refresh = true; 3990 4027 } … … 3998 4035 QString undoMessage = deleteMap.GetUndoMessage(); 3999 4036 QString redoMessage = deleteMap.GetRedoMessage(); 4000 handled = deleteMap.HandleAction(action, frame, framesPlayed, 4001 totalFrames, video_frame_rate); 4037 handled = deleteMap.HandleAction(action, frame, framesPlayed); 4002 4038 if (handled && (action == "CUTTOBEGINNING" || 4003 4039 action == "CUTTOEND" || action == "NEWCUT")) … … 4025 4061 if (osd) 4026 4062 { 4027 deleteMap.UpdateOSD(framesPlayed, totalFrames, video_frame_rate, 4028 osd); 4063 deleteMap.UpdateOSD(framesPlayed, video_frame_rate, osd); 4029 4064 } 4030 4065 osdLock.unlock(); … … 4041 4076 uint64_t MythPlayer::GetNearestMark(uint64_t frame, bool right) 4042 4077 { 4043 return deleteMap.GetNearestMark(frame, totalFrames,right);4078 return deleteMap.GetNearestMark(frame, right); 4044 4079 } 4045 4080 … … 4058 4093 if (deleteMap.GetSeekAmount() == -2) 4059 4094 { 4060 long long framenum = deleteMap.GetNearestMark(framesPlayed, 4061 totalFrames, right); 4095 uint64_t framenum = deleteMap.GetNearestMark(framesPlayed, right); 4062 4096 if (right && (framenum > (int64_t)framesPlayed)) 4063 4097 DoFastForward(framenum - framesPlayed, kInaccuracyNone); … … 4068 4102 { 4069 4103 if (right) 4070 {4071 4104 DoFastForward(2, kInaccuracyFull); 4072 }4073 4105 else 4074 {4075 4106 DoRewind(2, kInaccuracyFull); 4076 }4077 4107 } 4078 4108 } … … 4305 4335 { 4306 4336 uint64_t oldnumber = number; 4307 deleteMap.LoadMap( totalFrames);4337 deleteMap.LoadMap(); 4308 4338 commBreakMap.LoadMap(player_ctx, framesPlayed); 4309 4339 … … 4465 4495 4466 4496 if ((lastDecodedFrameNumber == 0) && honorCutList) 4467 deleteMap.TrackerReset(0 , 0);4497 deleteMap.TrackerReset(0); 4468 4498 4469 4499 if (!decoderThread) … … 4485 4515 4486 4516 uint64_t jumpto = 0; 4487 if (deleteMap.TrackerWantsToJump(lastDecodedFrameNumber, totalFrames, 4488 jumpto)) 4517 if (deleteMap.TrackerWantsToJump(lastDecodedFrameNumber, jumpto)) 4489 4518 { 4490 4519 LOG(VB_GENERAL, LOG_INFO, LOC + … … 4613 4642 } 4614 4643 4615 int64_t MythPlayer::GetSecondsPlayed(void)4616 {4617 #if 04618 return decoder->IsCodecMPEG() ?4619 (disp_timecode / 1000.f) :4620 (framesPlayed / video_frame_rate);4621 #else4622 return framesPlayed / video_frame_rate;4623 #endif4624 }4625 4626 4644 int64_t MythPlayer::GetTotalSeconds(void) const 4627 4645 { 4628 4646 return totalDuration; 4647 } 4648 4649 // Returns the total frame count, as totalFrames for a completed 4650 // recording, or the most recent frame count from the recorder for 4651 // live TV or an in-progress recording. 4652 uint64_t MythPlayer::GetCurrentFrameCount(void) const 4653 { 4654 uint64_t result = totalFrames; 4655 if (IsWatchingInprogress()) 4656 result = player_ctx->recorder->GetFramesWritten(); 4657 return result; 4658 } 4659 4660 // Finds the frame number associated with the given time offset. A 4661 // positive offset or +0.0f indicate offset from the beginning. A 4662 // negative offset or -0.0f indicate offset from the end. Limit the 4663 // result to within bounds of the video. 4664 uint64_t MythPlayer::FindFrame(float offset, bool use_cutlist) const 4665 { 4666 uint64_t length_ms = TranslatePositionFrameToMs(totalFrames, use_cutlist); 4667 uint64_t offset_ms = offset * 1000 + 0.5; 4668 if (signbit(offset)) 4669 offset_ms += length_ms; 4670 if (offset_ms < 0) 4671 offset_ms = 0; 4672 if (offset_ms > length_ms) 4673 offset_ms = length_ms; 4674 return TranslatePositionMsToFrame(offset_ms, use_cutlist); 4629 4675 } 4630 4676 … … 4645 4691 info.values.insert("progafter", 0); 4646 4692 4647 int playbackLen = GetTotalSeconds(); 4648 float secsplayed = (float)GetSecondsPlayed(); 4649 4650 if (totalDuration == 0 || decoder->GetCodecDecoderName() == "nuppel") 4693 uint64_t frames_played = framesPlayed; 4694 uint64_t total_frames = totalFrames; 4695 int playbackLen = 0; 4696 bool fixed_playbacklen = false; 4697 4698 if (decoder->GetCodecDecoderName() == "nuppel") 4699 { 4651 4700 playbackLen = totalLength; 4701 fixed_playbacklen = true; 4702 } 4652 4703 4653 4704 if (livetv && player_ctx->tvchain) … … 4657 4708 playbackLen = player_ctx->tvchain->GetLengthAtCurPos(); 4658 4709 islive = true; 4710 fixed_playbacklen = true; 4659 4711 } 4660 4712 else if (IsWatchingInprogress()) 4661 4713 { 4662 playbackLen = 4663 (int)(((float)player_ctx->recorder->GetFramesWritten() / 4664 video_frame_rate)); 4714 total_frames = player_ctx->recorder->GetFramesWritten(); 4665 4715 islive = true; 4666 4716 } … … 4692 4742 } 4693 4743 4694 playbackLen = max(playbackLen, 1);4695 secsplayed = min((float)playbackLen, max(secsplayed, 0.0f));4696 4697 4744 // Set the raw values, followed by the translated values. 4698 4745 for (int i = 0; i < 2 ; ++i) 4699 4746 { 4700 4747 QString relPrefix = (i == 0 ? "" : "rel"); 4701 if (i > 0) 4702 { 4703 playbackLen = deleteMap.TranslatePositionAbsToRel(playbackLen * video_frame_rate) / 4704 video_frame_rate; 4705 secsplayed = deleteMap.TranslatePositionAbsToRel(secsplayed * video_frame_rate) / 4706 video_frame_rate; 4707 } 4748 if (!fixed_playbacklen) 4749 playbackLen = 4750 TranslatePositionFrameToMs(total_frames, (i > 0)) 4751 / 1000; 4752 playbackLen = max(playbackLen, 1); 4753 float secsplayed = 4754 TranslatePositionFrameToMs(frames_played, (i > 0)) 4755 / 1000; 4756 secsplayed = min((float)playbackLen, max(secsplayed, 0.0f)); 4708 4757 4709 4758 info.values.insert(relPrefix + "secondsplayed", (int)secsplayed); … … 5058 5107 } 5059 5108 5060 bool MythPlayer::PosMapFromEnc(unsigned long long start, 5061 QMap<long long, long long> &posMap) 5109 bool MythPlayer::PosMapFromEnc(uint64_t start, 5110 frm_pos_map_t &posMap, 5111 frm_pos_map_t &durMap) 5062 5112 { 5063 5113 // Reads only new positionmap entries from encoder … … 5074 5124 5075 5125 player_ctx->recorder->FillPositionMap(start, -1, posMap); 5126 player_ctx->recorder->FillDurationMap(start, -1, durMap); 5076 5127 5077 5128 return true; -
mythtv/libs/libmythtv/mythplayer.h
r1eaecea6dd r49dbed5be 181 181 int GetLength(void) const { return totalLength; } 182 182 uint64_t GetTotalFrameCount(void) const { return totalFrames; } 183 uint64_t GetCurrentFrameCount(void) const; 183 184 uint64_t GetFramesPlayed(void) const { return framesPlayed; } 184 virtual int64_t GetSecondsPlayed(void);185 185 virtual int64_t GetTotalSeconds(void) const; 186 186 virtual uint64_t GetBookmark(void); … … 322 322 323 323 // Position Map Stuff 324 bool PosMapFromEnc(unsigned long long start, 325 QMap<long long, long long> &posMap); 324 bool PosMapFromEnc(uint64_t start, 325 frm_pos_map_t &posMap, 326 frm_pos_map_t &durMap); 326 327 327 328 // OSD locking for TV class … … 392 393 long long CalcRWTime(long long rw) const; 393 394 virtual void calcSliderPos(osdInfo &info, bool paddedFields = false); 394 uint64_t TranslatePositionAbsToRel(uint64_t absPosition) const { 395 return deleteMap.TranslatePositionAbsToRel(absPosition); 395 uint64_t TranslatePositionFrameToMs(uint64_t position, 396 bool use_cutlist) const { 397 return deleteMap.TranslatePositionFrameToMs(position, 398 GetFrameRate(), 399 use_cutlist); 396 400 } 397 uint64_t TranslatePositionRelToAbs(uint64_t relPosition) const { 398 return deleteMap.TranslatePositionRelToAbs(relPosition); 401 uint64_t TranslatePositionMsToFrame(uint64_t position, 402 bool use_cutlist) const { 403 return deleteMap.TranslatePositionMsToFrame(position, 404 GetFrameRate(), 405 use_cutlist); 399 406 } 407 // TranslatePositionAbsToRel and TranslatePositionRelToAbs are 408 // used for frame calculations when seeking relative to a number 409 // of frames rather than by time. 410 uint64_t TranslatePositionAbsToRel(uint64_t position) const { 411 return deleteMap.TranslatePositionAbsToRel(position); 412 } 413 uint64_t TranslatePositionRelToAbs(uint64_t position) const { 414 return deleteMap.TranslatePositionRelToAbs(position); 415 } 416 float ComputeSecs(uint64_t position, bool use_cutlist) const { 417 return TranslatePositionFrameToMs(position, use_cutlist) / 1000.0; 418 } 419 uint64_t FindFrame(float offset, bool use_cutlist) const; 400 420 401 421 // Commercial stuff … … 556 576 bool DoFastForward(uint64_t frames, double inaccuracy); 557 577 bool DoRewind(uint64_t frames, double inaccuracy); 578 bool DoFastForwardSecs(float secs, double inaccuracy, bool use_cutlist); 579 bool DoRewindSecs(float secs, double inaccuracy, bool use_cutlist); 558 580 void DoJumpToFrame(uint64_t frame, double inaccuracy); 559 581 -
mythtv/libs/libmythtv/nuppeldecoder.cpp
r1eaecea6dd r49dbed5be 379 379 ste.file_offset}; 380 380 m_positionMap.push_back(e); 381 uint64_t frame_num = ste.keyframe_number * keyframedist; 382 m_frameToDurMap[frame_num] = 383 frame_num * 1000 / video_frame_rate; 384 m_durToFrameMap[m_frameToDurMap[frame_num]] = frame_num; 381 385 } 382 386 hasFullPositionMap = true; … … 1153 1157 PosMapEntry e = {this_index, lastKey, currentposition}; 1154 1158 m_positionMap.push_back(e); 1159 m_frameToDurMap[lastKey] = 1160 lastKey * 1000 / video_frame_rate; 1161 m_durToFrameMap[m_frameToDurMap[lastKey]] = lastKey; 1155 1162 } 1156 1163 } -
mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
r1eaecea6dd r49dbed5be 82 82 _packet_count(0), 83 83 _continuity_error_count(0), 84 _frames_seen_count(0), _frames_written_count(0) 84 _frames_seen_count(0), _frames_written_count(0), 85 _frame_interval(0), _frame_duration(0), 86 _total_duration(0) 85 87 { 86 88 SetPositionMapType(MARK_GOP_BYFRAME); … … 160 162 curRecording->SaveFilesize(ringBuffer->GetRealFileSize()); 161 163 SavePositionMap(true); 164 curRecording->SaveTotalDuration((int64_t)_total_duration); 165 curRecording->SaveTotalFrames(_frames_written_count); 162 166 } 163 167 } … … 230 234 231 235 if (curRecording) 236 { 232 237 curRecording->ClearPositionMap(MARK_GOP_BYFRAME); 238 curRecording->ClearPositionMap(MARK_DURATION_MS); 239 } 233 240 } 234 241 … … 496 503 } 497 504 } 505 // The _repeat_pict code above matches 506 // mpegvideo_extract_headers(), but the 507 // code in mpeg_field_start() computes a 508 // value one less, which seems correct. 509 --_repeat_pict; 498 510 } 499 511 break; … … 534 546 _frames_seen_count++; 535 547 if (!_wait_for_keyframe_option || _first_keyframe>=0) 536 _frames_written_count++;548 UpdateFramesWritten(); 537 549 } 538 550 … … 627 639 } 628 640 641 void DTVRecorder::UpdateFramesWritten(void) 642 { 643 _frames_written_count++; 644 if (m_frameRate > 0) 645 { 646 // m_frameRate is frames per 1000 seconds, e.g. 29970 for 647 // 29.97 fps. Calculate usec values. 648 _frame_interval = 1000000000.0 / m_frameRate; 649 _frame_duration = _frame_interval + 650 (_repeat_pict * _frame_interval * 0.5f); 651 _total_duration += _frame_duration; 652 } 653 } 654 629 655 bool DTVRecorder::FindAudioKeyframes(const TSPacket*) 630 656 { … … 657 683 658 684 if (!_wait_for_keyframe_option || _first_keyframe>=0) 659 _frames_written_count++;685 UpdateFramesWritten(); 660 686 } 661 687 … … 677 703 678 704 _frames_seen_count++; 679 _frames_written_count++;705 UpdateFramesWritten(); 680 706 _last_keyframe_seen = _frames_seen_count; 681 707 … … 717 743 positionMapDelta[frameNum] = startpos; 718 744 positionMap[frameNum] = startpos; 745 durationMap[frameNum] = _total_duration / 1000; 746 durationMapDelta[frameNum] = _total_duration / 1000; 719 747 } 720 748 } … … 861 889 _frames_seen_count++; 862 890 if (!_wait_for_keyframe_option || _first_keyframe >= 0) 863 _frames_written_count++;891 UpdateFramesWritten(); 864 892 } 865 893 … … 908 936 positionMapDelta[frameNum] = m_h264_parser.keyframeAUstreamOffset(); 909 937 positionMap[frameNum] = m_h264_parser.keyframeAUstreamOffset(); 938 durationMap[frameNum] = _total_duration / 1000; 939 durationMapDelta[frameNum] = _total_duration / 1000; 910 940 } 911 941 positionMapLock.unlock(); … … 1027 1057 _frames_seen_count++; 1028 1058 if (!_wait_for_keyframe_option || _first_keyframe >= 0) 1029 _frames_written_count++;1059 UpdateFramesWritten(); 1030 1060 } 1031 1061 -
mythtv/libs/libmythtv/recorders/dtvrecorder.h
r1eaecea6dd r49dbed5be 96 96 void HandleKeyframe(uint64_t frameNum, int64_t extra = 0); 97 97 void HandleTimestamps(int stream_id, int64_t pts, int64_t dts); 98 void UpdateFramesWritten(void); 98 99 99 100 void BufferedWrite(const TSPacket &tspacket); … … 183 184 unsigned long long _frames_seen_count; 184 185 unsigned long long _frames_written_count; 186 double _frame_interval; // usec 187 double _frame_duration; // usec 188 double _total_duration; // usec 185 189 186 190 // constants -
mythtv/libs/libmythtv/recorders/recorderbase.cpp
r1eaecea6dd r49dbed5be 438 438 } 439 439 440 bool RecorderBase::GetKeyframeDurations( 441 int64_t start, int64_t end, frm_pos_map_t &map) const 442 { 443 map.clear(); 444 445 QMutexLocker locker(&positionMapLock); 446 if (durationMap.empty()) 447 return true; 448 449 frm_pos_map_t::const_iterator it = durationMap.lowerBound(start); 450 end = (end < 0) ? INT64_MAX : end; 451 for (; (it != durationMap.end()) && 452 (it.key() <= (uint64_t)end); ++it) 453 map[it.key()] = *it; 454 455 LOG(VB_GENERAL, LOG_INFO, LOC + 456 QString("GetKeyframeDurations(%1,%2,#%3) out of %4") 457 .arg(start).arg(end).arg(map.size()).arg(durationMap.size())); 458 459 return true; 460 } 461 440 462 /** \fn RecorderBase::SavePositionMap(bool) 441 463 * \brief This saves the postition map delta to the database if force … … 457 479 // save every 10 seconds later on 458 480 needToSave |= (delta_size >= 1) && (pm_elapsed >= 10000); 481 // Assume that durationMapDelta is the same size as 482 // positionMapDelta and implicitly use the same logic about when 483 // to same durationMapDelta. 459 484 460 485 if (curRecording && needToSave) … … 468 493 frm_pos_map_t deltaCopy(positionMapDelta); 469 494 positionMapDelta.clear(); 495 frm_pos_map_t durationDeltaCopy(durationMapDelta); 496 durationMapDelta.clear(); 470 497 positionMapLock.unlock(); 471 498 472 499 curRecording->SavePositionMapDelta(deltaCopy, positionMapType); 500 curRecording->SavePositionMapDelta(durationDeltaCopy, 501 MARK_DURATION_MS); 473 502 } 474 503 else -
mythtv/libs/libmythtv/recorders/recorderbase.h
r1eaecea6dd r49dbed5be 174 174 bool GetKeyframePositions( 175 175 int64_t start, int64_t end, frm_pos_map_t&) const; 176 bool GetKeyframeDurations( 177 int64_t start, int64_t end, frm_pos_map_t&) const; 176 178 177 179 virtual void StopRecording(void); … … 302 304 frm_pos_map_t positionMap; 303 305 frm_pos_map_t positionMapDelta; 306 frm_pos_map_t durationMap; 307 frm_pos_map_t durationMapDelta; 304 308 MythTimer positionMapTimer; 305 309 -
mythtv/libs/libmythtv/remoteencoder.cpp
r1eaecea6dd r49dbed5be 265 265 } 266 266 267 void RemoteEncoder::FillPositionMap( long long start, long longend,268 QMap<long long, long long>&positionMap)267 void RemoteEncoder::FillPositionMap(int64_t start, int64_t end, 268 frm_pos_map_t &positionMap) 269 269 { 270 270 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); … … 280 280 { 281 281 bool ok; 282 long longindex = (*it).toLongLong(&ok);282 uint64_t index = (*it).toLongLong(&ok); 283 283 if (++it == strlist.end() || !ok) 284 284 break; 285 285 286 long longpos = (*it).toLongLong(&ok);286 uint64_t pos = (*it).toLongLong(&ok); 287 287 if (!ok) 288 288 break; 289 289 290 290 positionMap[index] = pos; 291 } 292 } 293 294 void RemoteEncoder::FillDurationMap(int64_t start, int64_t end, 295 frm_pos_map_t &durationMap) 296 { 297 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 298 strlist << "FILL_DURATION_MAP"; 299 strlist << QString::number(start); 300 strlist << QString::number(end); 301 302 if (!SendReceiveStringList(strlist)) 303 return; 304 305 QStringList::const_iterator it = strlist.begin(); 306 for (; it != strlist.end(); ++it) 307 { 308 bool ok; 309 uint64_t index = (*it).toLongLong(&ok); 310 if (++it == strlist.end() || !ok) 311 break; 312 313 uint64_t pos = (*it).toLongLong(&ok); 314 if (!ok) 315 break; 316 317 durationMap[index] = pos; 291 318 } 292 319 } -
mythtv/libs/libmythtv/remoteencoder.h
r1eaecea6dd r49dbed5be 12 12 #include "videoouttypes.h" 13 13 #include "tv.h" 14 #include "programtypes.h" 14 15 15 16 class QStringList; … … 37 38 long long GetMaxBitrate(); 38 39 int64_t GetKeyframePosition(uint64_t desired); 39 void FillPositionMap(long long start, long long end, 40 QMap<long long, long long> &positionMap); 40 void FillPositionMap(int64_t start, int64_t end, 41 frm_pos_map_t &positionMap); 42 void FillDurationMap(int64_t start, int64_t end, 43 frm_pos_map_t &durationMap); 41 44 void StopPlaying(void); 42 45 void SpawnLiveTV(QString chainid, bool pip, QString startchan); -
mythtv/libs/libmythtv/tv_play.cpp
r1eaecea6dd r49dbed5be 4215 4215 ctx->LockDeletePlayer(__FILE__, __LINE__); 4216 4216 uint64_t bookmark = ctx->player->GetBookmark(); 4217 float rate = ctx->player->GetFrameRate();4218 float seekloc = ctx->player->TranslatePositionAbsToRel(bookmark) / rate;4219 4217 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 4220 4218 4221 if (bookmark > rate) 4222 DoSeek(ctx, seekloc, tr("Jump to Bookmark"), 4223 /*timeIsOffset*/false, 4224 /*honorCutlist*/true); 4219 if (bookmark) 4220 { 4221 DoPlayerSeekToFrame(ctx, bookmark); 4222 ctx->LockDeletePlayer(__FILE__, __LINE__); 4223 UpdateOSDSeekMessage(ctx, tr("Jump to Bookmark"), kOSDTimeout_Med); 4224 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 4225 } 4225 4226 } 4226 4227 else if (has_action(ACTION_JUMPSTART,actions)) … … 5047 5048 { 5048 5049 fplay = ctx->player->GetFramesPlayed(); 5049 rate = ctx->player->GetFrameRate(); 5050 rate = ctx->player->GetFrameRate(); // for display only 5050 5051 } 5051 5052 ctx->UnlockDeletePlayer(__FILE__, __LINE__); … … 6126 6127 else if (time < 0.0) 6127 6128 res = ctx->player->Rewind(-time); 6129 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 6130 6131 return res; 6132 } 6133 6134 bool TV::DoPlayerSeekToFrame(PlayerContext *ctx, uint64_t target) 6135 { 6136 if (!ctx || !ctx->buffer) 6137 return false; 6138 6139 LOG(VB_PLAYBACK, LOG_INFO, LOC + 6140 QString("DoPlayerSeekToFrame %1").arg(target)); 6141 6142 ctx->LockDeletePlayer(__FILE__, __LINE__); 6143 if (!ctx->player) 6144 { 6145 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 6146 return false; 6147 } 6148 6149 if (!ctx->buffer->IsSeekingAllowed()) 6150 { 6151 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 6152 return false; 6153 } 6154 6155 if (ctx == GetPlayer(ctx, 0)) 6156 PauseAudioUntilBuffered(ctx); 6157 6158 bool res = ctx->player->JumpToFrame(target); 6159 6128 6160 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 6129 6161 … … 6163 6195 if (!isDVD) 6164 6196 { 6165 float rate = 30.0f;6166 actx->LockDeletePlayer(__FILE__, __LINE__);6167 if (actx->player)6168 rate = actx->player->GetFrameRate();6169 actx->UnlockDeletePlayer(__FILE__, __LINE__);6170 float time = (flags & kAbsolute) ? direction :6171 direction * (1.001 / rate);6172 6197 QString message = (flags & kRewind) ? tr("Rewind") : 6173 6198 tr("Forward"); 6174 DoSeek(actx, time, message, 6175 /*timeIsOffset*/true, 6176 /*honorCutlist*/!(flags & kIgnoreCutlist)); 6199 actx->LockDeletePlayer(__FILE__, __LINE__); 6200 uint64_t frameAbs = actx->player->GetFramesPlayed(); 6201 uint64_t frameRel = 6202 actx->player->TranslatePositionAbsToRel(frameAbs); 6203 uint64_t targetRel = frameRel + direction; 6204 if (frameRel == 0 && direction < 0) 6205 targetRel = 0; 6206 uint64_t maxAbs = actx->player->GetCurrentFrameCount(); 6207 uint64_t maxRel = actx->player->TranslatePositionAbsToRel(maxAbs); 6208 if (targetRel > maxRel) 6209 targetRel = maxRel; 6210 uint64_t targetAbs = 6211 actx->player->TranslatePositionRelToAbs(targetRel); 6212 actx->UnlockDeletePlayer(__FILE__, __LINE__); 6213 DoPlayerSeekToFrame(actx, targetAbs); 6214 UpdateOSDSeekMessage(actx, message, kOSDTimeout_Med); 6177 6215 } 6178 6216 } … … 6214 6252 if (ctx->player->GetLimitKeyRepeat()) 6215 6253 limitkeys = true; 6216 ctx->UnlockDeletePlayer(__FILE__, __LINE__);6217 6254 6218 6255 if (!limitkeys || (keyRepeatTimer.elapsed() > (int)kKeyRepeatTimeout)) … … 6221 6258 NormalSpeed(ctx); 6222 6259 time += StopFFRew(ctx); 6223 float framerate = ctx->player->GetFrameRate();6224 6260 uint64_t currentFrameAbs = ctx->player->GetFramesPlayed(); 6225 uint64_t currentFrameRel = honorCutlist ? 6226 ctx->player->TranslatePositionAbsToRel(currentFrameAbs) : 6227 currentFrameAbs; 6228 int64_t desiredFrameRel = (timeIsOffset ? currentFrameRel : 0) + 6229 time * framerate + 0.5; 6230 if (desiredFrameRel < 0) 6231 desiredFrameRel = 0; 6232 uint64_t desiredFrameAbs = honorCutlist ? 6233 ctx->player->TranslatePositionRelToAbs(desiredFrameRel) : 6234 desiredFrameRel; 6235 time = ((int64_t)desiredFrameAbs - (int64_t)currentFrameAbs) / 6236 framerate; 6237 DoPlayerSeek(ctx, time); 6261 if (timeIsOffset) 6262 time += 6263 ctx->player->TranslatePositionFrameToMs(currentFrameAbs, 6264 honorCutlist) / 1000.0; 6265 if (time < 0) 6266 time = 0; 6267 uint64_t desiredFrameRel = 6268 ctx->player->TranslatePositionMsToFrame(time * 1000, honorCutlist); 6269 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 6270 DoPlayerSeekToFrame(ctx, desiredFrameRel); 6238 6271 UpdateOSDSeekMessage(ctx, mesg, kOSDTimeout_Med); 6239 6272 } 6273 else 6274 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 6240 6275 } 6241 6276 … … 6282 6317 return; 6283 6318 } 6284 time = (ctx->player->CalcMaxFFTime(LONG_MAX, false) / 6285 ctx->player->GetFrameRate()) - time; 6319 uint64_t total_frames = ctx->player->GetCurrentFrameCount(); 6320 float dur = ctx->player->ComputeSecs(total_frames, honorCutlist); 6321 time = max(0.0f, dur - time); 6286 6322 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 6287 DoSeek(ctx, time, tr("Jump To"), 6288 /*timeIsOffset*/(whence != ARBSEEK_SET), honorCutlist); 6323 DoSeek(ctx, time, tr("Jump To"), /*timeIsOffset*/false, honorCutlist); 6289 6324 } 6290 6325 else -
mythtv/libs/libmythtv/tv_play.h
r1eaecea6dd r49dbed5be 427 427 bool timeIsOffset, bool honorCutlist); 428 428 bool DoPlayerSeek(PlayerContext*, float time); 429 bool DoPlayerSeekToFrame(PlayerContext *ctx, uint64_t target); 429 430 enum ArbSeekWhence { 430 431 ARBSEEK_SET = 0, -
mythtv/libs/libmythtv/tv_rec.cpp
r1eaecea6dd r49dbed5be 2558 2558 } 2559 2559 2560 bool TVRec::GetKeyframeDurations( 2561 int64_t start, int64_t end, frm_pos_map_t &map) const 2562 { 2563 QMutexLocker lock(&stateChangeLock); 2564 2565 if (recorder) 2566 return recorder->GetKeyframeDurations(start, end, map); 2567 2568 return false; 2569 } 2570 2560 2571 /** \fn TVRec::GetMaxBitrate(void) const 2561 2572 * \brief Returns the maximum bits per second this recorder can produce. -
mythtv/libs/libmythtv/tv_rec.h
r1eaecea6dd r49dbed5be 183 183 int64_t GetKeyframePosition(uint64_t desired) const; 184 184 bool GetKeyframePositions(int64_t start, int64_t end, frm_pos_map_t&) const; 185 bool GetKeyframeDurations(int64_t start, int64_t end, frm_pos_map_t&) const; 185 186 void SpawnLiveTV(LiveTVChain *newchain, bool pip, QString startchan); 186 187 QString GetChainID(void); -
mythtv/programs/mythbackend/encoderlink.cpp
r1eaecea6dd r49dbed5be 573 573 } 574 574 575 bool EncoderLink::GetKeyframeDurations( 576 int64_t start, int64_t end, frm_pos_map_t &map) 577 { 578 if (!local) 579 { 580 LOG(VB_GENERAL, LOG_ERR, 581 "Should be local only query: GetKeyframeDurations"); 582 return false; 583 } 584 585 return tv->GetKeyframeDurations(start, end, map); 586 } 587 575 588 /** \fn EncoderLink::FrontendReady() 576 589 * \brief Tells TVRec that the frontend is ready for data. -
mythtv/programs/mythbackend/encoderlink.h
r1eaecea6dd r49dbed5be 103 103 int64_t GetKeyframePosition(uint64_t desired); 104 104 bool GetKeyframePositions(int64_t start, int64_t end, frm_pos_map_t&); 105 bool GetKeyframeDurations(int64_t start, int64_t end, frm_pos_map_t&); 105 106 void SpawnLiveTV(LiveTVChain *chain, bool pip, QString startchan); 106 107 QString GetChainID(void); -
mythtv/programs/mythbackend/mainserver.cpp
r1eaecea6dd r49dbed5be 3866 3866 else if (command == "FILL_POSITION_MAP") 3867 3867 { 3868 long longstart = slist[2].toLongLong();3869 long longend = slist[3].toLongLong();3868 int64_t start = slist[2].toLongLong(); 3869 int64_t end = slist[3].toLongLong(); 3870 3870 frm_pos_map_t map; 3871 3871 3872 3872 if (!enc->GetKeyframePositions(start, end, map)) 3873 { 3874 retlist << "error"; 3875 } 3876 else 3877 { 3878 frm_pos_map_t::const_iterator it = map.begin(); 3879 for (; it != map.end(); ++it) 3880 { 3881 retlist += QString::number(it.key()); 3882 retlist += QString::number(*it); 3883 } 3884 if (retlist.empty()) 3885 retlist << "OK"; 3886 } 3887 } 3888 else if (command == "FILL_DURATION_MAP") 3889 { 3890 int64_t start = slist[2].toLongLong(); 3891 int64_t end = slist[3].toLongLong(); 3892 frm_pos_map_t map; 3893 3894 if (!enc->GetKeyframeDurations(start, end, map)) 3873 3895 { 3874 3896 retlist << "error"; -
mythtv/programs/mythtranscode/cutter.cpp
r1eaecea6dd r49dbed5be 3 3 #include "cutter.h" 4 4 5 void Cutter::SetCutList(frm_dir_map_t &deleteMap )5 void Cutter::SetCutList(frm_dir_map_t &deleteMap, PlayerContext *ctx) 6 6 { 7 7 // Break each cut into two parts, the first for … … 12 12 int64_t leadinLength; 13 13 14 tracker.SetPlayerContext(ctx); 14 15 foreshortenedCutList.clear(); 15 16 … … 83 84 videoFramesToCut = 0; 84 85 audioFramesToCut = 0; 85 tracker.TrackerReset(0 , totalFrames);86 tracker.TrackerReset(0); 86 87 } 87 88 … … 94 95 uint64_t jumpTo = 0; 95 96 96 if (tracker.TrackerWantsToJump(currentFrame, totalFrames, 97 jumpTo)) 97 if (tracker.TrackerWantsToJump(currentFrame, jumpTo)) 98 98 { 99 99 // Reset the tracker and work out how much video and audio 100 100 // to drop 101 tracker.TrackerReset(jumpTo , totalFrames);101 tracker.TrackerReset(jumpTo); 102 102 videoFramesToCut = jumpTo - currentFrame; 103 103 audioFramesToCut += (int64_t)(videoFramesToCut * -
mythtv/programs/mythtranscode/cutter.h
r1eaecea6dd r49dbed5be 16 16 audioFramesPerVideoFrame(0.0) {}; 17 17 18 void SetCutList(frm_dir_map_t &deleteMap );18 void SetCutList(frm_dir_map_t &deleteMap, PlayerContext *ctx); 19 19 frm_dir_map_t AdjustedCutList() const; 20 20 void Activate(float v2a, int64_t total); -
mythtv/programs/mythtranscode/main.cpp
r1eaecea6dd r49dbed5be 44 44 pginfo->ClearPositionMap(MARK_GOP_START); 45 45 pginfo->SavePositionMap(posMap, MARK_GOP_BYFRAME); 46 pginfo->SavePositionMap(posMap, MARK_DURATION_MS); 46 47 } 47 48 else if (!mapfile.isEmpty()) 48 49 { 50 MarkTypes keyType = MARK_GOP_BYFRAME; 49 51 FILE *mapfh = fopen(mapfile.toLocal8Bit().constData(), "w"); 50 52 if (!mapfh) … … 55 57 } 56 58 frm_pos_map_t::const_iterator it; 57 fprintf (mapfh, "Type: %d\n", MARK_GOP_BYFRAME);59 fprintf (mapfh, "Type: %d\n", keyType); 58 60 for (it = posMap.begin(); it != posMap.end(); ++it) 59 fprintf(mapfh, "%lld %lld\n", 60 (unsigned long long)it.key(), (unsigned long long)*it); 61 if (it.key() == keyType) 62 fprintf(mapfh, "%lld %lld\n", 63 it.key(), *it); 61 64 fclose(mapfh); 62 65 } -
mythtv/programs/mythtranscode/mpeg2fix.cpp
r1eaecea6dd r49dbed5be 2661 2661 av_init_packet(&pkt); 2662 2662 2663 uint64_t totalDuration = 0; 2663 2664 while (av_read_frame(inputFC, &pkt) >= 0) 2664 2665 { … … 2667 2668 if (pkt.flags & AV_PKT_FLAG_KEY) 2668 2669 posMap[count] = pkt.pos; 2670 2671 // XXX totalDuration untested. Results should be the same 2672 // as from mythcommflag --rebuild. 2673 2674 // totalDuration calculation based on 2675 // AvFormatDecoder::PreProcessVideoPacket() 2676 totalDuration += 2677 av_q2d(inputFC->streams[pkt.stream_index]->time_base) * 2678 pkt.duration * 1000000; // usec 2679 posMap.insertMulti(count, totalDuration); 2669 2680 count++; 2670 2681 } -
mythtv/programs/mythtranscode/transcode.cpp
-
Property
mode
changed from
100755to100644
r1eaecea6dd r49dbed5be 800 800 // discard the rest 801 801 cutter = new Cutter(); 802 cutter->SetCutList(deleteMap); 803 802 cutter->SetCutList(deleteMap, ctx); 804 803 GetPlayer()->SetCutList(cutter->AdjustedCutList()); 805 804 } … … 1474 1473 m_proginfo->ClearPositionMap(MARK_GOP_START); 1475 1474 m_proginfo->ClearPositionMap(MARK_GOP_BYFRAME); 1475 m_proginfo->ClearPositionMap(MARK_DURATION_MS); 1476 1476 } 1477 1477 -
Property
mode
changed from
Note: See TracChangeset
for help on using the changeset viewer.
