Index: mythtv/libs/libmythtv/dvbrecorder.cpp
===================================================================
--- mythtv/libs/libmythtv/dvbrecorder.cpp	(revision 21402)
+++ mythtv/libs/libmythtv/dvbrecorder.cpp	(working copy)
@@ -156,6 +156,11 @@
     SetOption("videodevice", videodev);
     DTVRecorder::SetOption("tvformat", gContext->GetSetting("TVFormat"));
     SetStrOption(profile,  "recordingtype");
+    SetIntOption(profile, "transcode");
+    SetStrOption(profile, "videocodec");
+    SetIntOption(profile, "videobitrate");
+    SetStrOption(profile, "audiocodec");
+    SetIntOption(profile, "audiobitrate");
 }
 
 void DVBRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
@@ -562,10 +567,20 @@
     if (!_payload_buffer.empty())
     {
         if (ringBuffer)
-            ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+            if (doTranscode) {
+              transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+            }
+            else {
+              ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+            }
         _payload_buffer.clear();
     }
 
     if (ringBuffer)
-        ringBuffer->Write(tspacket.data(), TSPacket::SIZE);
+       if (doTranscode) {
+           transcoder->ringBuffer->Write((unsigned char*)tspacket.data(), TSPacket::SIZE);
+         }
+         else {
+           ringBuffer->Write(tspacket.data(), TSPacket::SIZE);
+         }
 }
Index: mythtv/libs/libmythtv/transcoder.h
===================================================================
--- mythtv/libs/libmythtv/transcoder.h	(revision 0)
+++ mythtv/libs/libmythtv/transcoder.h	(revision 0)
@@ -0,0 +1,44 @@
+// -*- Mode: c++ -*-
+/*
+ *  Copyright (C) Kenneth Aafloy 2003
+ *  
+ *  Copyright notice is in dvbrecorder.cpp of the MythTV project.
+ */
+
+#ifndef TRANSCODER_H
+#define TRANSCODER_H
+
+// C++ includes
+//#include <vector>
+//#include <deque>
+using namespace std;
+
+// Qt includes
+//#include "dtvrecorder.h"
+//#include "tspacket.h"
+//#include "DeviceReadBuffer.h"
+
+#include "RingBuffer.h"
+#include "RealRingBuffer.h"
+
+class Transcoder : public QThread {
+public:
+  Transcoder( RingBuffer *output, std::string a = "Transcoder" );
+  ~Transcoder();
+  void setParam(const QString &name, const QString &value);
+  void setParam(const QString &name, int value);
+  int Write( unsigned char *buf, int len );
+  RealRingBuffer *ringBuffer;
+  virtual void run();
+private:
+  std::string name;
+  RingBuffer *rb;
+  CodecID vcodec;
+  CodecID acodec;
+  int videobitrate;
+  int audiobitrate;
+  bool transcode_audio;
+  bool transcode_video;
+};
+
+#endif
Index: mythtv/libs/libmythtv/libmythtv.pro
===================================================================
--- mythtv/libs/libmythtv/libmythtv.pro	(revision 21402)
+++ mythtv/libs/libmythtv/libmythtv.pro	(working copy)
@@ -158,6 +158,7 @@
 HEADERS += transporteditor.h        listingsources.h
 HEADERS += myth_imgconvert.h
 HEADERS += channelgroup.h           channelgroupsettings.h
+HEADERS += RealRingBuffer.h         transcoder.h
 
 # Remove when everything is switched to MythUI
 HEADERS += proglist_qt.h
@@ -183,6 +184,7 @@
 SOURCES += transporteditor.cpp
 SOURCES += channelgroup.cpp         channelgroupsettings.cpp
 SOURCES += myth_imgconvert.cpp
+SOURCES += RealRingBuffer.cpp       transcoder.cpp
 
 # Remove when everything is switched to MythUI
 SOURCES += proglist_qt.cpp
Index: mythtv/libs/libmythtv/dvbrecorder.h
===================================================================
--- mythtv/libs/libmythtv/dvbrecorder.h	(revision 21402)
+++ mythtv/libs/libmythtv/dvbrecorder.h	(working copy)
@@ -123,6 +123,9 @@
     unsigned char _continuity_counter[0x1fff + 1];
     vector<TSPacket> _scratch;
 
+    //Transcoding
+    Transcoder	*tc;
+
     // Statistics
     mutable uint  _continuity_error_count;
     mutable uint  _stream_overflow_count;
Index: mythtv/libs/libmythtv/recorderbase.cpp
===================================================================
--- mythtv/libs/libmythtv/recorderbase.cpp	(revision 21402)
+++ mythtv/libs/libmythtv/recorderbase.cpp	(working copy)
@@ -32,7 +32,7 @@
       vbimode(0), ntsc(true), ntsc_framerate(true), video_frame_rate(29.97),
       m_videoAspect(0), m_videoHeight(0), m_videoWidth(0), curRecording(NULL),
       request_pause(false), paused(false), nextRingBuffer(NULL), nextRecording(NULL),
-      positionMapType(MARK_GOP_BYFRAME), positionMapLock()
+      positionMapType(MARK_GOP_BYFRAME), positionMapLock(), doTranscode(false)
 {
     QMutexLocker locker(&avcodeclock);
     avcodec_init(); // init CRC's
@@ -40,6 +40,12 @@
 
 RecorderBase::~RecorderBase(void)
 {
+    if (doTranscode) {
+       VERBOSE(VB_RECORD,  LOC + "Waiting for transcoder to finish...");
+       transcoder->wait();
+       VERBOSE(VB_RECORD,  LOC + "Transcoder finished!");
+       delete transcoder;
+    }
     if (weMadeBuffer && ringBuffer)
     {
         delete ringBuffer;
@@ -61,6 +67,15 @@
             msg = " '" + rbuf->GetFilename() + "'";
         VERBOSE(VB_RECORD,  LOC + "SetRingBuffer("<<rbuf<<")"<<msg);
     }
+    if (doTranscode) {
+      VERBOSE(VB_RECORD,  LOC + "Start transcoder");
+      transcoder = new Transcoder(rbuf, "TC");
+      transcoder->setParam("videocodec", videocodec);
+      transcoder->setParam("audiocodec", audiocodec);
+      transcoder->setParam("videobitrate", videobitrate);
+      transcoder->setParam("audiobitrate", audiobitrate);
+      transcoder->start();
+    }
     ringBuffer = rbuf;
     weMadeBuffer = false;
 }
@@ -87,6 +102,8 @@
 {
     if (name == "videocodec")
         videocodec = value;
+    else if (name == "audiocodec")
+        audiocodec = value;
     else if (name == "audiodevice")
         audiodevice = value;
     else if (name == "videodevice")
@@ -131,7 +148,14 @@
 
 void RecorderBase::SetOption(const QString &name, int value)
 {
-    VERBOSE(VB_IMPORTANT, LOC_ERR +
+    if (name == "videobitrate")
+        videobitrate = value;
+    else if (name == "audiobitrate")
+        audiobitrate = value;
+    else if (name == "transcode")
+        doTranscode = value;
+     else
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
             QString("SetOption(): Unknown int option: %1: %2")
             .arg(name).arg(value));
 }
@@ -139,8 +163,9 @@
 void RecorderBase::SetIntOption(RecordingProfile *profile, const QString &name)
 {
     const Setting *setting = profile->byName(name);
-    if (setting)
+    if (setting) {
         SetOption(name, setting->getValue().toInt());
+    }
     else
         VERBOSE(VB_IMPORTANT, LOC_ERR + QString(
                     "SetIntOption(...%1): Option not in profile.").arg(name));
Index: mythtv/libs/libmythtv/transcoder.cpp
===================================================================
--- mythtv/libs/libmythtv/transcoder.cpp	(revision 0)
+++ mythtv/libs/libmythtv/transcoder.cpp	(revision 0)
@@ -0,0 +1,392 @@
+#include "transcoder.h"
+#include "mythverbose.h"
+#include <stdio.h>
+#include <string.h>
+
+#define LOC QString("Transcoder: ")
+#define LOC_ERR QString("Transcoder Error: ")
+
+// AVLib/FFMPEG includes
+extern "C" {
+#include "libavcodec/avcodec.h"
+#include "libavformat/avformat.h"
+#include "libavformat/mpegts.h"
+}
+
+static int rb_open(URLContext *h, const char *filename, int flags) {
+    h->priv_data = (char *)strtoul(filename + 3, NULL, 16);
+    h->is_streamed = true;
+    return 0;
+}
+
+static int rb_read(URLContext *h, unsigned char *buf, int size) {
+    RealRingBuffer *rb = (RealRingBuffer *)h->priv_data;
+    int len = rb->Read(buf,size);
+    return len;
+}
+
+static int rb_write(URLContext *h, unsigned char *buf, int size) {
+    RealRingBuffer *rb = (RealRingBuffer *)h->priv_data;
+    return rb->Write(buf,size);
+}
+
+static int rb_close(URLContext *h) {
+    return 0;
+}
+
+
+static int rb1_open(URLContext *h, const char *filename, int flags) {
+    h->priv_data = (char *)strtoul(filename + 3, NULL, 16);
+    h->is_streamed = true;
+    return 0;
+}
+
+static int rb1_read(URLContext *h, unsigned char *buf, int size) {
+    RingBuffer *rb = (RingBuffer *)h->priv_data;
+    int len = rb->Read(buf,size);
+    return len;
+}
+
+static int rb1_write(URLContext *h, unsigned char *buf, int size) {
+    RingBuffer *rb = (RingBuffer *)h->priv_data;
+    return rb->Write(buf,size);
+}
+
+static int rb1_close(URLContext *h) {
+    RingBuffer *rb = (RingBuffer *)h->priv_data;
+    rb->WriterFlush();
+    return 0;
+}
+
+static int64_t rb1_seek(URLContext *h, int64_t os, int pos) {
+    return 0;
+}
+
+
+
+URLProtocol rb_protocol = {
+    "rb",
+    rb_open,
+    rb_read,
+    rb_write,
+    NULL,
+    rb_close,
+};
+
+URLProtocol rb1_protocol = {
+    "rc",
+    rb1_open,
+    rb1_read,
+    rb1_write,
+    rb1_seek,
+    rb1_close,
+};
+
+
+Transcoder::Transcoder(RingBuffer *rb1, std::string a ) : name(a)
+{
+    av_register_all();
+    register_protocol(&rb_protocol);
+    register_protocol(&rb1_protocol);
+    ringBuffer = new RealRingBuffer(1024*1024); //Let's try it with 1 MB... We might need to increase this.
+    rb = rb1;
+    vcodec = CODEC_ID_MPEG2VIDEO;
+    acodec = CODEC_ID_MP2;
+    transcode_video=true;
+    transcode_audio=true;
+}
+
+Transcoder::~Transcoder() {
+    delete ringBuffer;    
+}
+
+void Transcoder::setParam(const QString &name, int value)
+{
+  if (name == "videobitrate") {
+    videobitrate=value;
+  }
+  else if (name == "audiobitrate") {
+    audiobitrate=value;
+  }
+
+}
+
+void Transcoder::setParam(const QString &name, const QString &value)
+{
+  if (name == "videocodec") {
+    if (value == "mpeg4") {
+      vcodec = CODEC_ID_MPEG4;
+    }
+    else if (value == "wmv2") {
+      vcodec = CODEC_ID_WMV2;
+    }
+    else if (value == "mpeg2") {
+      vcodec = CODEC_ID_MPEG2VIDEO;
+    }
+    else {
+      transcode_video=false;
+    }
+  }
+  else if (name=="audiocodec") {
+    if (value == "mp2") {
+      acodec = CODEC_ID_MP2;
+    }
+    if (value == "wmav2") {
+      acodec = CODEC_ID_WMAV2;
+    }
+    else {
+       transcode_audio=false;
+    }
+  }
+
+}
+
+void Transcoder::run()
+{
+    int i;
+    AVPacket        packet;
+    AVFormatContext *pFormatCtxDecode;
+    AVFormatContext *pFormatCtxEncode;
+
+    // Open video
+    char buf[30];
+    sprintf((char *)&buf, "rb:%p",ringBuffer);
+    if(av_open_input_file(&pFormatCtxDecode, (char *)&buf, NULL, 0,  NULL)!=0) {
+        return; // Couldn't open file
+    }
+
+    // Retrieve stream information
+    if(av_find_stream_info(pFormatCtxDecode)<0)
+        return; // Couldn't find stream information
+
+    // Dump information about file onto standard error
+    //dump_format(pFormatCtxDecode, 0, (char *)&buf, false);
+    pFormatCtxDecode->flags |= AVFMT_NOFILE|AVFMT_FLAG_IGNIDX|AVFMT_NOTIMESTAMPS;
+
+    //Prepare Output
+    pFormatCtxEncode = av_alloc_format_context();
+    pFormatCtxEncode->oformat = guess_format("mpegts", NULL, NULL);
+    pFormatCtxEncode->flags |= AVFMT_NOFILE|AVFMT_FLAG_IGNIDX|AVFMT_NOTIMESTAMPS;
+    //char *outfile ="rb1:/blub1.mpg";
+    sprintf((char *)&buf, "rc:%p",rb);
+    memcpy(pFormatCtxEncode->filename, (char *)&buf, sizeof (pFormatCtxEncode->filename));
+
+    //Prepare Video Codec
+    AVCodec *pVideoCodecEncode=avcodec_find_encoder(vcodec);
+    if (pVideoCodecEncode==NULL) {
+      VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open video encoder!\n");
+      return;
+    }
+
+
+    //Prepare Audio Codec
+    AVCodec *pAudioCodecEncode=avcodec_find_encoder(acodec);
+    if (pAudioCodecEncode==NULL) {
+      VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open audio encoder!\n");
+      return;
+    }
+
+
+    // Copy the streams
+    for(i=0;i<pFormatCtxDecode->nb_streams; i++) {
+        AVStream *ist = pFormatCtxDecode->streams[i];
+        AVStream *ost = av_new_stream(pFormatCtxEncode, i);
+
+        if ((ist->codec->codec_type==CODEC_TYPE_VIDEO) && transcode_video) {
+            ost->codec = avcodec_alloc_context();
+
+            ost->codec->bit_rate = videobitrate*1000;
+            ost->codec->width = ist->codec->width;
+            ost->codec->height = ist->codec->height;
+            if(!ost->codec->width) ost->codec->width=720;
+            if(!ost->codec->height) ost->codec->height=576;
+
+            ost->codec->gop_size = 10; // emit one intra frame every ten frames
+            ost->codec->max_b_frames=5;
+            if (vcodec == CODEC_ID_WMV2) {
+               ost->codec->max_b_frames=0; //WMV2 does not accept b-frames
+            }
+            ost->codec->pix_fmt = (PixelFormat) 0;//ist->codec->pix_fmt;
+
+            if(av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) &&
+                    av_q2d(ist->time_base) < 1.0/1000)
+                ost->codec->time_base = ist->codec->time_base;
+            else
+                ost->codec->time_base = ist->time_base;
+
+
+            if (avcodec_open(ost->codec, pVideoCodecEncode) < 0) {
+                    fprintf(stderr, "could not open video codec!!!\n");
+                    return;
+            }
+
+            AVCodec *pCodecDecode=avcodec_find_decoder(ist->codec->codec_id);
+            if(pCodecDecode==NULL) {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open video decoder!\n");
+                return;
+            }
+
+            if(avcodec_open(ist->codec, pCodecDecode)<0) {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open video decoder!\n");
+                return;
+            }
+
+
+        }
+        else if ((ist->codec->codec_type==CODEC_TYPE_AUDIO) && transcode_audio) {
+            ost->codec = avcodec_alloc_context();
+            ost->codec->bit_rate = audiobitrate*1000;
+            ost->codec->me_method = ist->codec->me_method;
+            ost->codec->sample_fmt = ist->codec->sample_fmt;
+                            if(!ost->codec->width) ost->codec->width=720;
+                    if(!ost->codec->height) ost->codec->height=576;
+
+            //if(!ost->codec->codec_tag){
+            //    if(  pFormatCtxEncode->oformat->codec_tag
+            //        || av_codec_get_id (pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_tag) > 0
+            //        || av_codec_get_tag(pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_id) <= 0)
+            //        ost->codec->codec_tag = ist->codec->codec_tag;
+            //}
+
+            ost->codec->extradata = ist->codec->extradata;
+            ost->codec->extradata_size = ist->codec->extradata_size;
+
+
+
+            if(av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) &&
+                    av_q2d(ist->time_base) < 1.0/1000)
+                ost->codec->time_base = ist->codec->time_base;
+            else
+                ost->codec->time_base = ist->time_base;
+
+            ost->codec->sample_rate = 48000;
+            ost->codec->channels = ist->codec->channels?ist->codec->channels:2;
+            ost->codec->block_align= 0;
+
+            if (avcodec_open(ost->codec, pAudioCodecEncode) < 0) {
+                    fprintf(stderr, "could not open audio codec!!!\n");
+                    return;
+            }
+
+            AVCodec *pCodecDecode=avcodec_find_decoder(ist->codec->codec_id);
+            if(pCodecDecode==NULL) {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open audio decoder!\n");
+                return;
+            }
+
+            if(avcodec_open(ist->codec, pCodecDecode)<0) {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open audio decoder!\n");
+                return;
+            }
+
+
+        }
+        else {
+            ost->stream_copy=1;
+            ost->codec->codec_id = ist->codec->codec_id;
+            ost->codec->codec_type = ist->codec->codec_type;
+            ost->codec->codec_tag = ist->codec->codec_tag;
+            memcpy(ost->codec->codec_name,ist->codec->codec_name,sizeof(ost->codec->codec_name));
+            ost->codec->sub_id = ist->codec->sub_id;
+            ost->codec->me_method = ist->codec->me_method;
+            ost->codec->sample_fmt = ist->codec->sample_fmt;
+
+            //if(!ost->codec->codec_tag){
+            //    if(  pFormatCtxEncode->oformat->codec_tag
+            //        || av_codec_get_id (pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_tag) > 0
+            //        || av_codec_get_tag(pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_id) <= 0)
+            //        ost->codec->codec_tag = ist->codec->codec_tag;
+            //}
+
+            ost->codec->bit_rate = ist->codec->bit_rate;
+            ost->codec->extradata = ist->codec->extradata;
+            ost->codec->extradata_size = ist->codec->extradata_size;
+
+            if(av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) &&
+                    av_q2d(ist->time_base) < 1.0/1000)
+                ost->codec->time_base = ist->codec->time_base;
+            else
+                ost->codec->time_base = ist->time_base;
+
+            switch(ost->codec->codec_type) {
+                case CODEC_TYPE_AUDIO:
+                    ost->codec->sample_rate = ist->codec->sample_rate?ist->codec->sample_rate:48000;
+                    ost->codec->channels = ist->codec->channels?ist->codec->channels:2;
+                    ost->codec->frame_size = ist->codec->frame_size;
+                    ost->codec->block_align= ist->codec->block_align;
+                    if(ost->codec->block_align == 1 && ost->codec->codec_id == CODEC_ID_MP3)
+                        ost->codec->block_align=0;
+                        break;
+                case CODEC_TYPE_VIDEO:
+                    ost->codec->pix_fmt = ist->codec->pix_fmt;
+                    ost->codec->width = ist->codec->width;
+                    ost->codec->height = ist->codec->height;
+                    ost->codec->has_b_frames = ist->codec->has_b_frames;
+                    if(!ost->codec->width) ost->codec->width=720;
+                    if(!ost->codec->height) ost->codec->height=576;
+                    break;
+                case CODEC_TYPE_SUBTITLE:
+                    break;
+                default:
+                    break;
+            }
+
+            ost->pts.num = ist->pts.num;
+            ost->pts.den = ist->pts.den;
+        }
+    }
+
+    //dump_format(pFormatCtxEncode, i, pFormatCtxEncode->filename, 1);
+    url_fopen (&pFormatCtxEncode->pb, pFormatCtxEncode->filename, URL_WRONLY);
+    av_write_header (pFormatCtxEncode);
+
+    AVFrame *pFrame = avcodec_alloc_frame();
+    int frameFinished;
+    int outbuf_size = 100000;
+    uint8_t *outbuf = new uint8_t[outbuf_size];
+    int audiosamplesize=AVCODEC_MAX_AUDIO_FRAME_SIZE;
+    int16_t *audiosample = new int16_t[audiosamplesize];
+
+    //Copy or Transcode
+    while (av_read_frame(pFormatCtxDecode, &packet) >= 0) {
+        if (pFormatCtxEncode->streams[packet.stream_index]->stream_copy) {
+	     if (av_write_frame (pFormatCtxEncode, &packet))
+                VERBOSE(VB_RECORD, LOC + "Write frame failed!\n");
+        }
+        else {
+            if (pFormatCtxDecode->streams[packet.stream_index]->codec->codec_type==CODEC_TYPE_VIDEO) {
+                avcodec_decode_video(pFormatCtxDecode->streams[packet.stream_index]->codec, pFrame, &frameFinished, packet.data, packet.size);
+                if(frameFinished)
+                {
+                     int out_size = avcodec_encode_video(pFormatCtxEncode->streams[packet.stream_index]->codec, outbuf, outbuf_size, (AVFrame*)pFrame);
+                    //printf("encoding frame %3d (size=%5d)\n", i, out_size);
+                    //AVPacket avpkt;
+                    //av_init_packet(&avpkt);
+                    //avpkt.stream_index = packet.stream_index;
+                    //avpkt.data=outbuf;
+                    //avpkt.size=out_size;
+                    //avpkt.dts = packet.dts;
+                    //avpkt.pts = packet.pts;
+                    packet.data=outbuf;
+                    packet.size=out_size;
+                    //avpkt.duration = packet.duration;
+                    av_write_frame(pFormatCtxEncode, &packet);
+                }
+            }
+            else {
+                audiosamplesize=AVCODEC_MAX_AUDIO_FRAME_SIZE;
+                avcodec_decode_audio2(pFormatCtxDecode->streams[packet.stream_index]->codec, audiosample, &audiosamplesize, packet.data, packet.size);
+                int out_size = avcodec_encode_audio( pFormatCtxEncode->streams[packet.stream_index]->codec, outbuf, outbuf_size, audiosample );
+                packet.data=outbuf;
+                packet.size=out_size;
+                av_write_frame(pFormatCtxEncode, &packet);
+
+
+            }
+        }
+        //av_free_packet (&packet);
+    }
+    delete pFormatCtxEncode;
+    delete pFormatCtxDecode;
+    return;
+}
Index: mythtv/libs/libmythtv/dtvrecorder.cpp
===================================================================
--- mythtv/libs/libmythtv/dtvrecorder.cpp	(revision 21402)
+++ mythtv/libs/libmythtv/dtvrecorder.cpp	(working copy)
@@ -104,6 +104,9 @@
             VERBOSE(VB_IMPORTANT, LOC_ERR +
                     "Could not allocate new packet buffer.");
     }
+    else {
+       RecorderBase::SetOption(name, value);
+    }
 }
 
 /** \fn DTVRecorder::FinishRecording(void)
@@ -116,10 +119,20 @@
     {
         if (_payload_buffer.size())
         {
-            ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+	    if (doTranscode) {
+              transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+            }
+            else {
+              ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+            }
             _payload_buffer.clear();
         }
-        ringBuffer->WriterFlush();
+        if (doTranscode) {
+          transcoder->ringBuffer->SetEOF();
+        }
+        else {
+          ringBuffer->WriterFlush();
+        }
     }
 
     if (curRecording)
@@ -193,13 +206,23 @@
     // we have to write them first...
     if (!_payload_buffer.empty())
     {
-        if (ringBuffer)
-            ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+        if (doTranscode) {
+          transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+        }
+        else {
+          ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+        }
         _payload_buffer.clear();
     }
 
     if (ringBuffer)
-        ringBuffer->Write(tspacket.data(), TSPacket::SIZE);
+       if (doTranscode) {
+           transcoder->ringBuffer->Write((unsigned char*)tspacket.data(), TSPacket::SIZE);
+         }
+         else {
+           ringBuffer->Write(tspacket.data(), TSPacket::SIZE);
+         }
+
 }
 
 /** \fn DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
@@ -401,7 +424,12 @@
     SavePositionMap(true);
     if (ringBuffer)
     {
-        ringBuffer->WriterFlush();
+        if (doTranscode) {
+            transcoder->ringBuffer->SetEOF();
+        }
+        else {
+            ringBuffer->WriterFlush();
+        }
         if (curRecording)
             curRecording->SetFilesize(ringBuffer->GetRealFileSize());
     }
@@ -736,14 +764,24 @@
             {
                 if (ringBuffer)
                 {
-                    ringBuffer->Write(
-                        &_payload_buffer[0], _payload_buffer.size());
+                    if (doTranscode) {
+                        transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+                    }
+                    else {
+                        ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
+                    }
+
                 }
                 _payload_buffer.clear();
             }
 
             if (ringBuffer)
-                ringBuffer->Write(bufstart, (bufptr - bufstart));
+                if (doTranscode) {
+                    transcoder->ringBuffer->Write((unsigned char*)bufstart, (bufptr - bufstart));
+                }
+                else {
+                    ringBuffer->Write(bufstart, (bufptr - bufstart));
+                }
 
             bufstart = bufptr;
         }
Index: mythtv/libs/libmythtv/recorderbase.h
===================================================================
--- mythtv/libs/libmythtv/recorderbase.h	(revision 21402)
+++ mythtv/libs/libmythtv/recorderbase.h	(working copy)
@@ -11,6 +11,7 @@
 #include <pthread.h>
 
 #include "mythexp.h"
+#include "transcoder.h"
 
 class TVRec;
 class RingBuffer;
@@ -257,10 +258,13 @@
     bool           weMadeBuffer;
 
     QString        videocodec;
+    QString        audiocodec;
     QString        audiodevice;
     QString        videodevice;
     QString        vbidevice;
 
+    int            videobitrate;
+    int            audiobitrate;
     int            vbimode;
     bool           ntsc;
     bool           ntsc_framerate;
@@ -290,6 +294,10 @@
     PosMap         positionMap;
     PosMap         positionMapDelta;
 
+    //Transcode
+    bool           doTranscode;
+    Transcoder    *transcoder;
+
 };
 
 #endif
Index: mythtv/libs/libmythtv/RealRingBuffer.h
===================================================================
--- mythtv/libs/libmythtv/RealRingBuffer.h	(revision 0)
+++ mythtv/libs/libmythtv/RealRingBuffer.h	(revision 0)
@@ -0,0 +1,30 @@
+#ifndef REALRINGBUFFER_H
+#define REALRINGBUFFER_H
+
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+
+using namespace std;
+
+class RealRingBuffer {
+public:
+  RealRingBuffer( int size );
+  ~RealRingBuffer();
+  int Write( unsigned char *buf, int len );
+  int Read( unsigned char *buf, int len );
+  void SetEOF();
+  bool IsEOF();
+private:
+  char *rb;
+  int rbsize;
+  int rbrpos;
+  int rbwpos;
+  int bytes;
+  bool eof;
+  QMutex mutex;
+  QWaitCondition needData;
+  QWaitCondition needSpace;
+};
+
+#endif
Index: mythtv/libs/libmythtv/recordingprofile.cpp
===================================================================
--- mythtv/libs/libmythtv/recordingprofile.cpp	(revision 21402)
+++ mythtv/libs/libmythtv/recordingprofile.cpp	(working copy)
@@ -528,6 +528,83 @@
     };
 };
 
+
+class VideoBitrate : public SliderSetting, public CodecParamStorage
+{
+  public:
+    VideoBitrate(const RecordingProfile &parent) :
+        SliderSetting(this, 100, 8000, 100),
+        CodecParamStorage(this, parent, "videobitrate")
+    {
+        setLabel(QObject::tr("Video Bitrate"));
+        setValue(2200);
+        setHelpText(QObject::tr("Bitrate in kilobits/second.  2200Kbps is "
+                    "approximately 1 Gigabyte per hour."));
+    };
+};
+
+class AudioBitrate : public SliderSetting, public CodecParamStorage
+{
+  public:
+    AudioBitrate(const RecordingProfile &parent) :
+        SliderSetting(this, 32, 320, 16),
+        CodecParamStorage(this, parent, "audiobitrate")
+    {
+        setLabel(QObject::tr("Audio Bitrate"));
+        setValue(2200);
+        setHelpText(QObject::tr("Bitrate in kilobits/second."));
+    };
+};
+
+class VideoCodec : public ComboBoxSetting, public CodecParamStorage
+{
+  public:
+    VideoCodec(const RecordingProfile &parent) :
+        ComboBoxSetting(this),
+        CodecParamStorage(this, parent, "videocodec")
+    {
+        setLabel(QObject::tr("Video Codec"));
+
+        addSelection("mpeg2");
+        addSelection("mpeg4");
+        addSelection("wmv2");
+        setValue(0);
+        setHelpText(QObject::tr("Sets the video codec."));
+    };
+};
+
+class AudioCodec : public ComboBoxSetting, public CodecParamStorage
+{
+  public:
+    AudioCodec(const RecordingProfile &parent) :
+        ComboBoxSetting(this),
+        CodecParamStorage(this, parent, "audiocodec")
+    {
+        setLabel(QObject::tr("Audio Codec"));
+
+        addSelection("mp2");
+        addSelection("wmav2");
+
+        setValue(0);
+        setHelpText(QObject::tr("Sets the audio codec."));
+    };
+};
+
+
+class Transcode : public CheckBoxSetting, public CodecParamStorage
+{
+  public:
+    Transcode(const RecordingProfile &parent) :
+        CheckBoxSetting(this),
+        CodecParamStorage(this, parent, "transcode")
+    {
+        setLabel(QObject::tr("Enable transcoding"));
+        setValue(true);
+        setHelpText(QObject::tr("If set, transcoding gets enabled."));
+    };
+};
+
+
 class ScaleBitrate : public CheckBoxSetting, public CodecParamStorage
 {
   public:
@@ -795,6 +872,41 @@
     };
 };
 
+class TranscoderSettings : public TriggeredConfigurationGroup
+{
+  public:
+    TranscoderSettings(const RecordingProfile &parent, QString profName) :
+        TriggeredConfigurationGroup(false, true, false, false)
+    {
+        QString labelName;
+        labelName = QObject::tr("Transcoder");
+        setName(labelName);
+
+        transcode = new Transcode(parent);
+        addChild(transcode);
+        setTrigger(transcode);
+
+        ConfigurationGroup* params = new VerticalConfigurationGroup();
+        params->setLabel(QObject::tr("Video Parameters"));
+        params->addChild(new VideoCodec(parent));
+        params->addChild(new VideoBitrate(parent));
+
+        //addTarget("transcode", params);
+
+        //params = new VerticalConfigurationGroup();
+        //params->setLabel(QObject::tr("Audio Parameters"));
+        params->addChild(new AudioCodec(parent));
+        params->addChild(new AudioBitrate(parent));
+
+        addTarget("transcode", params);
+
+    }
+
+private:
+    Transcode* transcode;
+};
+
+
 class VideoCompressionSettings : public TriggeredConfigurationGroup
 {
   public:
@@ -1290,6 +1402,7 @@
     else if (type.toUpper() == "DVB")
     {
         addChild(new RecordingType(*this));
+        addChild(new TranscoderSettings(*this, profileName));
     }
 
     id->setValue(profileId);
Index: mythtv/libs/libmythtv/RealRingBuffer.cpp
===================================================================
--- mythtv/libs/libmythtv/RealRingBuffer.cpp	(revision 0)
+++ mythtv/libs/libmythtv/RealRingBuffer.cpp	(revision 0)
@@ -0,0 +1,92 @@
+#include "RealRingBuffer.h"
+#include "mythverbose.h"
+
+#define LOC QString("RealRingBuffer: ")
+#define LOC_ERR QString("RealRingBuffer Error: ")
+
+
+RealRingBuffer::RealRingBuffer(int size) {
+  rbsize=size;
+  eof=false;
+  rbrpos=0;
+  rbwpos=0;
+  bytes=0;
+  rb = new char[size];
+}
+
+RealRingBuffer::~RealRingBuffer() {
+  delete rb;
+}
+
+bool RealRingBuffer::IsEOF() {
+  return eof;
+}
+
+void RealRingBuffer::SetEOF() {
+  QMutexLocker locker(&mutex);
+  eof=true;
+  needData.wakeAll();
+}
+
+int RealRingBuffer::Read(unsigned char *buf, int size) {
+    int len = 0;
+
+    QMutexLocker locker(&mutex);
+
+    if (eof && bytes==0) {
+        return -1;
+    }
+
+    while (size>0) {
+
+        if (bytes==0) {
+            if (eof) {
+                return len;
+            }
+            needData.wait(&mutex);
+        }
+
+        int rby = bytes > size ? size : bytes;
+
+        if (rbrpos+rby>rbsize) {
+            rby = rbsize-rbrpos;
+        }
+
+        memcpy(buf, rb + rbrpos, rby);
+        size -= rby;
+        buf += rby;
+        bytes -= rby;
+        len += rby;
+        rbrpos = (rbrpos + rby)%rbsize;
+        needSpace.wakeAll();
+    }
+    return len;
+}
+
+int RealRingBuffer::Write(unsigned char *buf, int size) {
+    int len = 0;
+    QMutexLocker locker(&mutex);
+
+    while (size>0) {
+
+        if (rbsize-bytes==0) {
+            VERBOSE(VB_RECORD, LOC + "Ringbuffer is full. Waiting for data read.");
+            needSpace.wait(&mutex);
+        }
+
+        int wb = rbsize-bytes>size ? size : rbsize-bytes;
+
+        if (rbwpos+wb>rbsize) {
+            wb = rbsize-rbwpos;
+        }
+
+        memcpy(rb+rbwpos,buf,wb);
+        size -= wb;
+        buf += wb;
+        bytes += wb;
+        len += wb;
+        rbwpos = (rbwpos + wb)%rbsize;
+        needData.wakeAll();
+    }
+    return len;
+}

