diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/programinfo.cpp myth.20207.0313b/mythtv/libs/libmythtv/programinfo.cpp
--- mythtv/libs/libmythtv/programinfo.cpp	2009-03-14 12:02:22.000000000 -0500
+++ mythtv/libs/libmythtv/programinfo.cpp	2009-03-19 00:06:58.000000000 -0500
@@ -1704,6 +1704,117 @@
     return tmpURL;
 }
 
+bool ProgramInfo::DuplicateForTranscoding()
+{
+    // Create new recording basename and update this object to identify as transcoded
+    // recording:
+    //   Modify the recgroupd -> "Deleted"
+    //   Set to autoexpire
+    //   Insert it all into the database
+    //   Copy the current seek table and markup to the new recording keys
+    //
+
+    if (!record)
+    {
+        record = new ScheduledRecording();
+        record->loadByProgram(this);
+    }
+
+    QString dirname = pathname;
+    QDateTime from_recstartts = recstartts;
+    QString from_pathname = pathname;
+
+    recgroup = "Deleted";
+
+    QString ext = pathname.section('.', -1);
+
+    hostname = gContext->GetHostName();
+    pathname = CreateRecordBasename(ext);
+
+    int count = 0;
+    while (!insert_program(this, record) && count < 50)
+    {
+        recstartts = recstartts.addSecs(1);
+        pathname = CreateRecordBasename(ext);
+        count++;
+    }
+
+    if (count >= 50)
+    {
+        VERBOSE(VB_IMPORTANT, "Couldn't insert program for transcode");
+        return false;
+    }
+
+    VERBOSE(VB_GENERAL, QString("Orig: %1, New: %2").arg(from_pathname).arg(pathname));
+
+    // Set to autoexpire
+    SetAutoExpire(kDeletedAutoExpire);
+    UpdateLastDelete(true);
+
+    MSqlQuery query(MSqlQuery::InitCon());
+
+    // Copy the original recordedseek
+    query.prepare("CREATE TEMPORARY TABLE tmp_recordedseek"
+                  " SELECT * FROM recordedseek WHERE chanid = :CHANID"
+                  " AND starttime = :START;");
+
+    query.bindValue(":CHANID", chanid);
+    query.bindValue(":START", from_recstartts);
+
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Create temp table recordedseek on program duplicate", query);
+
+    // Update recordedseek to have the new starttime
+    query.prepare("UPDATE tmp_recordedseek SET starttime = :START;");
+    query.bindValue(":START", recstartts);
+
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Update tmp table on program duplicate", query);
+
+    // Copy back into the real recordedseek table
+    query.prepare("INSERT INTO recordedseek SELECT * from tmp_recordedseek;");
+
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Copy back into recordedseek on program duplicate", query);
+
+    query.prepare("DROP TABLE tmp_recordedseek;");
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Drop temp table recordedseek on program duplicate", query);
+
+
+    // Do the same thing for recordedmarkup
+
+    // Copy the original recordedmarkup
+    query.prepare("CREATE TEMPORARY TABLE tmp_recordedmarkup"
+                  " SELECT * FROM recordedmarkup WHERE chanid = :CHANID"
+                  " AND starttime = :START;");
+
+    query.bindValue(":CHANID", chanid);
+    query.bindValue(":START", from_recstartts);
+
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Create temp table recordedmarkup on program duplicate", query);
+
+    // Update recordedseek to have the new starttime
+    query.prepare("UPDATE tmp_recordedmarkup SET starttime = :START;");
+    query.bindValue(":START", recstartts);
+
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Update tmp table on program duplicate", query);
+
+    // Copy back into the real recordedmarkup table
+    query.prepare("INSERT INTO recordedmarkup SELECT * from tmp_recordedmarkup;");
+
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Copy back into recordedmarkup on program duplicate", query);
+
+    query.prepare("DROP TABLE tmp_recordedmarkup;");
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Drop temp table recordedmarkup on program duplicate", query);
+
+    return true;
+}
+
 /**
  *  \brief Inserts this ProgramInfo into the database as an existing recording.
  *
@@ -1815,7 +1926,8 @@
         if (!query.isActive())
             MythDB::DBError("insert_program -- select", query);
         else
-            VERBOSE(VB_IMPORTANT, "recording already exists...");
+            VERBOSE(VB_IMPORTANT, QString("recording already exists for chanid %1 starttime %2")
+                                  .arg(pg->chanid).arg(pg->recstartts.toString("yyyyMMddhhmmss")));
 
         if (!query.exec("UNLOCK TABLES"))
             MythDB::DBError("insert_program -- unlock tables", query);
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/programinfo.h myth.20207.0313b/mythtv/libs/libmythtv/programinfo.h
--- mythtv/libs/libmythtv/programinfo.h	2009-02-27 06:30:56.000000000 -0600
+++ mythtv/libs/libmythtv/programinfo.h	2009-03-18 23:53:22.000000000 -0500
@@ -237,6 +237,12 @@
                                    const QString &newSubtitle);
     void ApplyTranscoderProfileChange(QString);
 
+    // If we're transcoding and saving the original file, this
+    // will duplicate the ProgramInfo so both the original and
+    // Transcoded recording exist in MythTV
+    // returns true if successful
+    bool DuplicateForTranscoding();
+
     // Quick gets
     bool SetRecordBasename(QString basename);
     QString GetRecordBasename(bool fromDB = false) const;
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/remoteutil.cpp myth.20207.0313b/mythtv/libs/libmythtv/remoteutil.cpp
--- mythtv/libs/libmythtv/remoteutil.cpp	2009-03-12 06:30:58.000000000 -0500
+++ mythtv/libs/libmythtv/remoteutil.cpp	2009-03-18 23:53:22.000000000 -0500
@@ -273,7 +273,8 @@
     bool result = false;
 
     bool undelete_possible = 
-            gContext->GetNumSetting("AutoExpireInsteadOfDelete", 0);
+            gContext->GetNumSetting("AutoExpireInsteadOfDelete", 0) ||
+            gContext->GetNumSetting("SaveTranscoding", 0);
 
     if (!undelete_possible)
         return result;
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/programs/mythbackend/mainserver.cpp myth.20207.0313b/mythtv/programs/mythbackend/mainserver.cpp
--- mythtv/programs/mythbackend/mainserver.cpp	2009-03-14 12:02:22.000000000 -0500
+++ mythtv/programs/mythbackend/mainserver.cpp	2009-03-18 23:55:28.000000000 -0500
@@ -2246,7 +2246,8 @@
 {
     bool ret = -1;
     bool undelete_possible =
-            gContext->GetNumSetting("AutoExpireInsteadOfDelete", 0);
+            gContext->GetNumSetting("AutoExpireInsteadOfDelete", 0) ||
+            gContext->GetNumSetting("SaveTranscoding", 0);
     MythSocket *pbssock = NULL;
     if (pbs)
         pbssock = pbs->getSocket();
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/programs/mythtranscode/main.cpp myth.20207.0313b/mythtv/programs/mythtranscode/main.cpp
--- mythtv/programs/mythtranscode/main.cpp	2009-03-06 00:26:28.000000000 -0600
+++ mythtv/programs/mythtranscode/main.cpp	2009-03-18 23:59:59.000000000 -0500
@@ -27,7 +27,7 @@
                        ProgramInfo *pginfo);
 int BuildKeyframeIndex(MPEG2fixup *m2f, QString &infile,
                        QMap <long long, long long> &posMap, int jobID);
-void CompleteJob(int jobID, ProgramInfo *pginfo,
+void CompleteJob(int jobID, ProgramInfo *pginfo, ProgramInfo *saved_pginfo,
                  bool useCutlist, int &resultCode);
 void UpdateJobQueue(float percent_done);
 int CheckJobQueue();
@@ -498,6 +498,7 @@
     }
 
     ProgramInfo *pginfo = NULL;
+    ProgramInfo *saved_pginfo = NULL; // in case we keep the original recording as deleted
     if (isVideo)
     {
         // We want the absolute file path for the filemarkup table
@@ -522,6 +523,17 @@
         }
 
         infile = pginfo->GetPlaybackURL(false, true);
+
+        // If we're saving the old file we need to save the cut and markup info now
+        if (gContext->GetNumSetting("SaveTranscoding", 0))
+        {
+            saved_pginfo = new ProgramInfo(*pginfo);
+            if (!saved_pginfo->DuplicateForTranscoding())
+            {
+                delete saved_pginfo;
+                saved_pginfo = NULL;
+            }
+        }
     }
     else
     {
@@ -673,10 +685,13 @@
     }
 
     if (jobID >= 0)
-        CompleteJob(jobID, pginfo, useCutlist, exitcode);
+        CompleteJob(jobID, pginfo, saved_pginfo, useCutlist, exitcode);
 
     transcode->deleteLater();
 
+    if (saved_pginfo)
+        delete saved_pginfo;
+
     delete gContext;
     return exitcode;
 }
@@ -815,7 +830,7 @@
     return unlink(filename.toLocal8Bit().constData());
 }
 
-void CompleteJob(int jobID, ProgramInfo *pginfo, bool useCutlist, int &resultCode)
+void CompleteJob(int jobID, ProgramInfo *pginfo, ProgramInfo *saved_pginfo, bool useCutlist, int &resultCode)
 {
     int status = JobQueue::GetJobStatus(jobID);
 
@@ -868,7 +883,37 @@
                     .arg(tmpfile).arg(newfile) + ENO);
         }
 
-        if (!gContext->GetNumSetting("SaveTranscoding", 0))
+        if (gContext->GetNumSetting("SaveTranscoding", 0))
+        {
+            if (saved_pginfo)
+            {
+                // Get a new (old) filename
+                // and move the old transcode file to the new (old) filename
+
+                // Can't use GetPlaybackURL() because the target file doesn't exist yet.
+
+                QString origfilename = saved_pginfo->GetFileName();
+                QString origbasename = origfilename.section('/', -1);
+
+                QString dirname = oldfile.section('/', 0, -2);
+
+                QString origpath = dirname + "/" + origbasename;
+
+                if (rename(oldfile.local8Bit(), origpath.local8Bit()) == -1)
+                    perror(QString("mythtranscode: Error Renaming '%1' to '%2'")
+                           .arg(oldfile).arg(origpath).ascii());
+
+
+                // If we transcoded a "Deleted" program, undelete the output recording
+                if (pginfo->recgroup == "Deleted")
+                {
+                    pginfo->ApplyRecordRecGroupChange("Default");
+                    pginfo->UpdateLastDelete(false);
+                    pginfo->SetAutoExpire(kDisableAutoExpire);
+                }
+            }
+        }
+        else
         {
             int err;
             bool followLinks = gContext->GetNumSetting("DeletesFollowLinks", 0);
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/programs/mythtv-setup/backendsettings.cpp myth.20207.0313b/mythtv/programs/mythtv-setup/backendsettings.cpp
--- mythtv/programs/mythtv-setup/backendsettings.cpp	2009-03-02 06:30:31.000000000 -0600
+++ mythtv/programs/mythtv-setup/backendsettings.cpp	2009-03-18 23:53:22.000000000 -0500
@@ -122,7 +122,7 @@
     gc->setLabel(QObject::tr("Save original files after transcoding (globally)"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("When set and the transcoder is active, the "
-                    "original files will be renamed to .old once the "
+                    "original recording will be moved to the 'Deleted' recording group once the "
                     "transcoding is complete."));
     return gc;
 };
