Index: libs/libmythtv/dvbrecorder.cpp
===================================================================
--- libs/libmythtv/dvbrecorder.cpp	(revision 21402)
+++ 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,24 @@
     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: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 21402)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -1185,7 +1185,7 @@
 
         if (stream->sample_aspect_ratio.num)
             aspect_ratio = av_q2d(stream->sample_aspect_ratio);
-        else if (enc->sample_aspect_ratio.num == 0)
+        else if (enc->sample_aspect_ratio.num)
             aspect_ratio = av_q2d(enc->sample_aspect_ratio);
         else
             aspect_ratio = 1.0f;
Index: libs/libmythtv/transcoder.h
===================================================================
--- libs/libmythtv/transcoder.h	(revision 0)
+++ libs/libmythtv/transcoder.h	(revision 0)
@@ -0,0 +1,48 @@
+// -*- Mode: c++ -*-
+/*
+ *  Copyright (C) Rene Buehlmann 2009
+ *  
+ *  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;
+    int width;
+    int height;
+    bool transcode_audio;
+    bool transcode_video;
+};
+
+#endif
+
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro	(revision 21402)
+++ 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: libs/libmythtv/dvbrecorder.h
===================================================================
--- libs/libmythtv/dvbrecorder.h	(revision 21402)
+++ 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: libs/libmythtv/recorderbase.cpp
===================================================================
--- libs/libmythtv/recorderbase.cpp	(revision 21402)
+++ 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,14 @@
 
 RecorderBase::~RecorderBase(void)
 {
+    if (doTranscode)
+    {
+        VERBOSE(VB_RECORD,  LOC + "Waiting for transcoder to finish...");
+        transcoder->wait();
+        VERBOSE(VB_RECORD,  LOC + "Transcoder finished!");
+        delete transcoder;
+        transcoder = NULL;
+    }
     if (weMadeBuffer && ringBuffer)
     {
         delete ringBuffer;
@@ -61,6 +69,16 @@
             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 +105,8 @@
 {
     if (name == "videocodec")
         videocodec = value;
+    else if (name == "audiocodec")
+        audiocodec = value;
     else if (name == "audiodevice")
         audiodevice = value;
     else if (name == "videodevice")
@@ -131,7 +151,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));
 }
@@ -227,7 +254,16 @@
         ResetForNewFile();
 
         m_videoAspect = m_videoWidth = m_videoHeight = 0;
-
+	
+    if (doTranscode)
+    {
+        VERBOSE(VB_RECORD,  LOC + "Waiting for transcoder to finish...");
+        transcoder->wait();
+        VERBOSE(VB_RECORD,  LOC + "Transcoder finished!");
+        delete transcoder;
+        transcoder = NULL;
+    }
+						   
         if (weMadeBuffer && ringBuffer)
             delete ringBuffer;
         SetRingBuffer(nextRingBuffer);
Index: libs/libmythtv/transcoder.cpp
===================================================================
--- libs/libmythtv/transcoder.cpp	(revision 0)
+++ libs/libmythtv/transcoder.cpp	(revision 0)
@@ -0,0 +1,531 @@
+// -*- Mode: c++ -*-
+/*
+ *  Copyright (C) Rene Buehlmann 2009
+ *
+ *  Copyright notice is in dvbrecorder.cpp of the MythTV project.
+ */
+
+#include "transcoder.h"
+#include "mythverbose.h"
+#include "format.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"
+#include "libswscale/swscale.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 == "height")
+    {
+        height = value;
+    }
+    else if (name == "width")
+    {
+        width = 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;
+    SwsContext *scaleContext;
+
+    // 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;
+    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->codec_type = ist->codec->codec_type;
+            ost->codec->bit_rate = videobitrate * 1000;
+            ost->codec->ildct_cmp = ist->codec->ildct_cmp;
+            ost->codec->sample_aspect_ratio.num
+                    = ist->codec->sample_aspect_ratio.num;
+            ost->codec->sample_aspect_ratio.den
+                    = ist->codec->sample_aspect_ratio.den;
+            ost->sample_aspect_ratio.num = ist->codec->sample_aspect_ratio.num;
+            ost->sample_aspect_ratio.den = ist->codec->sample_aspect_ratio.den;
+            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->pix_fmt = ist->codec->pix_fmt;
+
+            if (height != 0 && width != 0 && (ost->codec->width != width
+                    || ost->codec->height != height))
+            {
+                ost->codec->width = width;
+                ost->codec->height = height;
+                scaleContext = sws_getContext(ist->codec->width,
+                        ist->codec->height, ist->codec->pix_fmt, width, height,
+                        ost->codec->pix_fmt, 1, NULL, NULL, NULL);
+                if (!scaleContext)
+                {
+                    VERBOSE(VB_IMPORTANT, LOC_ERR
+                            + "Could not create scale context!\n");
+                    return;
+                }
+            }
+
+            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
+            }
+
+            //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->codec->time_base;
+            //ost->time_base = ist->codec->time_base;
+            //fixed framerate for now
+            ost->time_base.num=1;
+            ost->time_base.den=25;
+            ost->codec->time_base.num=1;
+            ost->codec->time_base.den=25;
+
+            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->codec_type = ist->codec->codec_type;
+            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();
+    AVFrame *newFrame = pFrame;
+    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];
+
+    //For scaling
+    AVPicture *newPicture;
+    uint8_t *buffer;
+    if (scaleContext)
+    {
+        int numBytes = avpicture_get_size(
+                pFormatCtxEncode->streams[0]->codec->pix_fmt, width, height);
+        buffer = new uint8_t[numBytes];
+        memset(buffer, 0, numBytes);
+        newPicture = new AVPicture();
+        newFrame = avcodec_alloc_frame();
+        avpicture_fill((AVPicture *) newPicture, buffer,
+                pFormatCtxEncode->streams[0]->codec->pix_fmt, width, height);
+    }
+
+    //Copy or Transcode
+    while (av_read_frame(pFormatCtxDecode, &packet) >= 0)
+    {
+        //only two streams for now..
+        if (packet.stream_index > 2)
+        {
+            continue;
+        }
+        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)
+                {
+                    //Do rescale?
+                    if (scaleContext)
+                    {
+                        sws_scale(
+                                scaleContext,
+                                pFrame->data,
+                                pFrame->linesize,
+                                0,
+                                pFormatCtxDecode->streams[packet.stream_index]->codec->height,
+                                newPicture->data, newPicture->linesize);
+                        newFrame->data[0] = newPicture->data[0];
+                        newFrame->linesize[0] = newPicture->linesize[0];
+                        newFrame->data[1] = newPicture->data[1];
+                        newFrame->linesize[1] = newPicture->linesize[1];
+                        newFrame->data[2] = newPicture->data[2];
+                        newFrame->linesize[2] = newPicture->linesize[2];
+                        newFrame->data[3] = newPicture->data[3];
+                        newFrame->linesize[3] = newPicture->linesize[3];
+                    }
+
+                    int
+                            out_size =
+                                    avcodec_encode_video(
+                                            pFormatCtxEncode->streams[packet.stream_index]->codec,
+                                            outbuf, outbuf_size,
+                                            (AVFrame*) newFrame);
+                    packet.data = outbuf;
+                    packet.size = out_size;
+                    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);
+
+            }
+        }
+    }
+    if (scaleContext)
+    {
+        sws_freeContext(scaleContext);
+        delete buffer;
+        delete newPicture;
+    }
+    av_free_packet(&packet);
+    delete pFrame;
+    delete pFormatCtxEncode;
+    delete pFormatCtxDecode;
+    delete outbuf;
+    delete audiosample;
+    return;
+}
+
Index: libs/libmythtv/dtvrecorder.cpp
===================================================================
--- libs/libmythtv/dtvrecorder.cpp	(revision 21402)
+++ libs/libmythtv/dtvrecorder.cpp	(working copy)
@@ -104,6 +104,10 @@
             VERBOSE(VB_IMPORTANT, LOC_ERR +
                     "Could not allocate new packet buffer.");
     }
+    else
+    {
+       RecorderBase::SetOption(name, value);
+    }
 }
 
 /** \fn DTVRecorder::FinishRecording(void)
@@ -116,10 +120,24 @@
     {
         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 +211,26 @@
     // we have to write them first...
     if (!_payload_buffer.empty())
     {
-        if (ringBuffer)
+        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 +432,14 @@
     SavePositionMap(true);
     if (ringBuffer)
     {
-        ringBuffer->WriterFlush();
+        if (doTranscode)
+        {
+            transcoder->ringBuffer->SetEOF();
+        }
+        else
+        {
+            ringBuffer->WriterFlush();
+        }
         if (curRecording)
             curRecording->SetFilesize(ringBuffer->GetRealFileSize());
     }
@@ -736,14 +774,26 @@
             {
                 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: libs/libmythtv/recorderbase.h
===================================================================
--- libs/libmythtv/recorderbase.h	(revision 21402)
+++ 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: libs/libmythtv/RealRingBuffer.h
===================================================================
--- libs/libmythtv/RealRingBuffer.h	(revision 0)
+++ libs/libmythtv/RealRingBuffer.h	(revision 0)
@@ -0,0 +1,39 @@
+// -*- Mode: c++ -*-
+/*
+ *  Copyright (C) Rene Buehlmann 2009
+ *  
+ *  Copyright notice is in dvbrecorder.cpp of the MythTV project.
+ */
+
+#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: libs/libmythtv/recordingprofile.cpp
===================================================================
--- libs/libmythtv/recordingprofile.cpp	(revision 21402)
+++ 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: libs/libmythtv/RealRingBuffer.cpp
===================================================================
--- libs/libmythtv/RealRingBuffer.cpp	(revision 0)
+++ libs/libmythtv/RealRingBuffer.cpp	(revision 0)
@@ -0,0 +1,113 @@
+// -*- Mode: c++ -*-
+/*
+ *  Copyright (C) Rene Buehlmann 2009
+ *  
+ *  Copyright notice is in dvbrecorder.cpp of the MythTV project.
+ */
+
+#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;
+}


