Ticket #6888: live_transcode.patch

File live_transcode.patch, 31.2 KB (added by buehlmann@…, 3 years ago)
  • mythtv/libs/libmythtv/dvbrecorder.cpp

     
    156156    SetOption("videodevice", videodev); 
    157157    DTVRecorder::SetOption("tvformat", gContext->GetSetting("TVFormat")); 
    158158    SetStrOption(profile,  "recordingtype"); 
     159    SetIntOption(profile, "transcode"); 
     160    SetStrOption(profile, "videocodec"); 
     161    SetIntOption(profile, "videobitrate"); 
     162    SetStrOption(profile, "audiocodec"); 
     163    SetIntOption(profile, "audiobitrate"); 
    159164} 
    160165 
    161166void DVBRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 
     
    562567    if (!_payload_buffer.empty()) 
    563568    { 
    564569        if (ringBuffer) 
    565             ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     570            if (doTranscode) { 
     571              transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     572            } 
     573            else { 
     574              ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     575            } 
    566576        _payload_buffer.clear(); 
    567577    } 
    568578 
    569579    if (ringBuffer) 
    570         ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 
     580       if (doTranscode) { 
     581           transcoder->ringBuffer->Write((unsigned char*)tspacket.data(), TSPacket::SIZE); 
     582         } 
     583         else { 
     584           ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 
     585         } 
    571586} 
  • mythtv/libs/libmythtv/transcoder.h

     
     1// -*- Mode: c++ -*- 
     2/* 
     3 *  Copyright (C) Kenneth Aafloy 2003 
     4 *   
     5 *  Copyright notice is in dvbrecorder.cpp of the MythTV project. 
     6 */ 
     7 
     8#ifndef TRANSCODER_H 
     9#define TRANSCODER_H 
     10 
     11// C++ includes 
     12//#include <vector> 
     13//#include <deque> 
     14using namespace std; 
     15 
     16// Qt includes 
     17//#include "dtvrecorder.h" 
     18//#include "tspacket.h" 
     19//#include "DeviceReadBuffer.h" 
     20 
     21#include "RingBuffer.h" 
     22#include "RealRingBuffer.h" 
     23 
     24class Transcoder : public QThread { 
     25public: 
     26  Transcoder( RingBuffer *output, std::string a = "Transcoder" ); 
     27  ~Transcoder(); 
     28  void setParam(const QString &name, const QString &value); 
     29  void setParam(const QString &name, int value); 
     30  int Write( unsigned char *buf, int len ); 
     31  RealRingBuffer *ringBuffer; 
     32  virtual void run(); 
     33private: 
     34  std::string name; 
     35  RingBuffer *rb; 
     36  CodecID vcodec; 
     37  CodecID acodec; 
     38  int videobitrate; 
     39  int audiobitrate; 
     40  bool transcode_audio; 
     41  bool transcode_video; 
     42}; 
     43 
     44#endif 
  • mythtv/libs/libmythtv/libmythtv.pro

     
    158158HEADERS += transporteditor.h        listingsources.h 
    159159HEADERS += myth_imgconvert.h 
    160160HEADERS += channelgroup.h           channelgroupsettings.h 
     161HEADERS += RealRingBuffer.h         transcoder.h 
    161162 
    162163# Remove when everything is switched to MythUI 
    163164HEADERS += proglist_qt.h 
     
    183184SOURCES += transporteditor.cpp 
    184185SOURCES += channelgroup.cpp         channelgroupsettings.cpp 
    185186SOURCES += myth_imgconvert.cpp 
     187SOURCES += RealRingBuffer.cpp       transcoder.cpp 
    186188 
    187189# Remove when everything is switched to MythUI 
    188190SOURCES += proglist_qt.cpp 
  • mythtv/libs/libmythtv/dvbrecorder.h

     
    123123    unsigned char _continuity_counter[0x1fff + 1]; 
    124124    vector<TSPacket> _scratch; 
    125125 
     126    //Transcoding 
     127    Transcoder  *tc; 
     128 
    126129    // Statistics 
    127130    mutable uint  _continuity_error_count; 
    128131    mutable uint  _stream_overflow_count; 
  • mythtv/libs/libmythtv/recorderbase.cpp

     
    3232      vbimode(0), ntsc(true), ntsc_framerate(true), video_frame_rate(29.97), 
    3333      m_videoAspect(0), m_videoHeight(0), m_videoWidth(0), curRecording(NULL), 
    3434      request_pause(false), paused(false), nextRingBuffer(NULL), nextRecording(NULL), 
    35       positionMapType(MARK_GOP_BYFRAME), positionMapLock() 
     35      positionMapType(MARK_GOP_BYFRAME), positionMapLock(), doTranscode(false) 
    3636{ 
    3737    QMutexLocker locker(&avcodeclock); 
    3838    avcodec_init(); // init CRC's 
     
    4040 
    4141RecorderBase::~RecorderBase(void) 
    4242{ 
     43    if (doTranscode) { 
     44       VERBOSE(VB_RECORD,  LOC + "Waiting for transcoder to finish..."); 
     45       transcoder->wait(); 
     46       VERBOSE(VB_RECORD,  LOC + "Transcoder finished!"); 
     47       delete transcoder; 
     48    } 
    4349    if (weMadeBuffer && ringBuffer) 
    4450    { 
    4551        delete ringBuffer; 
     
    6167            msg = " '" + rbuf->GetFilename() + "'"; 
    6268        VERBOSE(VB_RECORD,  LOC + "SetRingBuffer("<<rbuf<<")"<<msg); 
    6369    } 
     70    if (doTranscode) { 
     71      VERBOSE(VB_RECORD,  LOC + "Start transcoder"); 
     72      transcoder = new Transcoder(rbuf, "TC"); 
     73      transcoder->setParam("videocodec", videocodec); 
     74      transcoder->setParam("audiocodec", audiocodec); 
     75      transcoder->setParam("videobitrate", videobitrate); 
     76      transcoder->setParam("audiobitrate", audiobitrate); 
     77      transcoder->start(); 
     78    } 
    6479    ringBuffer = rbuf; 
    6580    weMadeBuffer = false; 
    6681} 
     
    87102{ 
    88103    if (name == "videocodec") 
    89104        videocodec = value; 
     105    else if (name == "audiocodec") 
     106        audiocodec = value; 
    90107    else if (name == "audiodevice") 
    91108        audiodevice = value; 
    92109    else if (name == "videodevice") 
     
    131148 
    132149void RecorderBase::SetOption(const QString &name, int value) 
    133150{ 
    134     VERBOSE(VB_IMPORTANT, LOC_ERR + 
     151    if (name == "videobitrate") 
     152        videobitrate = value; 
     153    else if (name == "audiobitrate") 
     154        audiobitrate = value; 
     155    else if (name == "transcode") 
     156        doTranscode = value; 
     157     else 
     158        VERBOSE(VB_IMPORTANT, LOC_ERR + 
    135159            QString("SetOption(): Unknown int option: %1: %2") 
    136160            .arg(name).arg(value)); 
    137161} 
     
    139163void RecorderBase::SetIntOption(RecordingProfile *profile, const QString &name) 
    140164{ 
    141165    const Setting *setting = profile->byName(name); 
    142     if (setting) 
     166    if (setting) { 
    143167        SetOption(name, setting->getValue().toInt()); 
     168    } 
    144169    else 
    145170        VERBOSE(VB_IMPORTANT, LOC_ERR + QString( 
    146171                    "SetIntOption(...%1): Option not in profile.").arg(name)); 
  • mythtv/libs/libmythtv/transcoder.cpp

     
     1#include "transcoder.h" 
     2#include "mythverbose.h" 
     3#include <stdio.h> 
     4#include <string.h> 
     5 
     6#define LOC QString("Transcoder: ") 
     7#define LOC_ERR QString("Transcoder Error: ") 
     8 
     9// AVLib/FFMPEG includes 
     10extern "C" { 
     11#include "libavcodec/avcodec.h" 
     12#include "libavformat/avformat.h" 
     13#include "libavformat/mpegts.h" 
     14} 
     15 
     16static int rb_open(URLContext *h, const char *filename, int flags) { 
     17    h->priv_data = (char *)strtoul(filename + 3, NULL, 16); 
     18    h->is_streamed = true; 
     19    return 0; 
     20} 
     21 
     22static int rb_read(URLContext *h, unsigned char *buf, int size) { 
     23    RealRingBuffer *rb = (RealRingBuffer *)h->priv_data; 
     24    int len = rb->Read(buf,size); 
     25    return len; 
     26} 
     27 
     28static int rb_write(URLContext *h, unsigned char *buf, int size) { 
     29    RealRingBuffer *rb = (RealRingBuffer *)h->priv_data; 
     30    return rb->Write(buf,size); 
     31} 
     32 
     33static int rb_close(URLContext *h) { 
     34    return 0; 
     35} 
     36 
     37 
     38static int rb1_open(URLContext *h, const char *filename, int flags) { 
     39    h->priv_data = (char *)strtoul(filename + 3, NULL, 16); 
     40    h->is_streamed = true; 
     41    return 0; 
     42} 
     43 
     44static int rb1_read(URLContext *h, unsigned char *buf, int size) { 
     45    RingBuffer *rb = (RingBuffer *)h->priv_data; 
     46    int len = rb->Read(buf,size); 
     47    return len; 
     48} 
     49 
     50static int rb1_write(URLContext *h, unsigned char *buf, int size) { 
     51    RingBuffer *rb = (RingBuffer *)h->priv_data; 
     52    return rb->Write(buf,size); 
     53} 
     54 
     55static int rb1_close(URLContext *h) { 
     56    RingBuffer *rb = (RingBuffer *)h->priv_data; 
     57    rb->WriterFlush(); 
     58    return 0; 
     59} 
     60 
     61static int64_t rb1_seek(URLContext *h, int64_t os, int pos) { 
     62    return 0; 
     63} 
     64 
     65 
     66 
     67URLProtocol rb_protocol = { 
     68    "rb", 
     69    rb_open, 
     70    rb_read, 
     71    rb_write, 
     72    NULL, 
     73    rb_close, 
     74}; 
     75 
     76URLProtocol rb1_protocol = { 
     77    "rc", 
     78    rb1_open, 
     79    rb1_read, 
     80    rb1_write, 
     81    rb1_seek, 
     82    rb1_close, 
     83}; 
     84 
     85 
     86Transcoder::Transcoder(RingBuffer *rb1, std::string a ) : name(a) 
     87{ 
     88    av_register_all(); 
     89    register_protocol(&rb_protocol); 
     90    register_protocol(&rb1_protocol); 
     91    ringBuffer = new RealRingBuffer(1024*1024); //Let's try it with 1 MB... We might need to increase this. 
     92    rb = rb1; 
     93    vcodec = CODEC_ID_MPEG2VIDEO; 
     94    acodec = CODEC_ID_MP2; 
     95    transcode_video=true; 
     96    transcode_audio=true; 
     97} 
     98 
     99Transcoder::~Transcoder() { 
     100    delete ringBuffer;     
     101} 
     102 
     103void Transcoder::setParam(const QString &name, int value) 
     104{ 
     105  if (name == "videobitrate") { 
     106    videobitrate=value; 
     107  } 
     108  else if (name == "audiobitrate") { 
     109    audiobitrate=value; 
     110  } 
     111 
     112} 
     113 
     114void Transcoder::setParam(const QString &name, const QString &value) 
     115{ 
     116  if (name == "videocodec") { 
     117    if (value == "mpeg4") { 
     118      vcodec = CODEC_ID_MPEG4; 
     119    } 
     120    else if (value == "wmv2") { 
     121      vcodec = CODEC_ID_WMV2; 
     122    } 
     123    else if (value == "mpeg2") { 
     124      vcodec = CODEC_ID_MPEG2VIDEO; 
     125    } 
     126    else { 
     127      transcode_video=false; 
     128    } 
     129  } 
     130  else if (name=="audiocodec") { 
     131    if (value == "mp2") { 
     132      acodec = CODEC_ID_MP2; 
     133    } 
     134    if (value == "wmav2") { 
     135      acodec = CODEC_ID_WMAV2; 
     136    } 
     137    else { 
     138       transcode_audio=false; 
     139    } 
     140  } 
     141 
     142} 
     143 
     144void Transcoder::run() 
     145{ 
     146    int i; 
     147    AVPacket        packet; 
     148    AVFormatContext *pFormatCtxDecode; 
     149    AVFormatContext *pFormatCtxEncode; 
     150 
     151    // Open video 
     152    char buf[30]; 
     153    sprintf((char *)&buf, "rb:%p",ringBuffer); 
     154    if(av_open_input_file(&pFormatCtxDecode, (char *)&buf, NULL, 0,  NULL)!=0) { 
     155        return; // Couldn't open file 
     156    } 
     157 
     158    // Retrieve stream information 
     159    if(av_find_stream_info(pFormatCtxDecode)<0) 
     160        return; // Couldn't find stream information 
     161 
     162    // Dump information about file onto standard error 
     163    //dump_format(pFormatCtxDecode, 0, (char *)&buf, false); 
     164    pFormatCtxDecode->flags |= AVFMT_NOFILE|AVFMT_FLAG_IGNIDX|AVFMT_NOTIMESTAMPS; 
     165 
     166    //Prepare Output 
     167    pFormatCtxEncode = av_alloc_format_context(); 
     168    pFormatCtxEncode->oformat = guess_format("mpegts", NULL, NULL); 
     169    pFormatCtxEncode->flags |= AVFMT_NOFILE|AVFMT_FLAG_IGNIDX|AVFMT_NOTIMESTAMPS; 
     170    //char *outfile ="rb1:/blub1.mpg"; 
     171    sprintf((char *)&buf, "rc:%p",rb); 
     172    memcpy(pFormatCtxEncode->filename, (char *)&buf, sizeof (pFormatCtxEncode->filename)); 
     173 
     174    //Prepare Video Codec 
     175    AVCodec *pVideoCodecEncode=avcodec_find_encoder(vcodec); 
     176    if (pVideoCodecEncode==NULL) { 
     177      VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open video encoder!\n"); 
     178      return; 
     179    } 
     180 
     181 
     182    //Prepare Audio Codec 
     183    AVCodec *pAudioCodecEncode=avcodec_find_encoder(acodec); 
     184    if (pAudioCodecEncode==NULL) { 
     185      VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open audio encoder!\n"); 
     186      return; 
     187    } 
     188 
     189 
     190    // Copy the streams 
     191    for(i=0;i<pFormatCtxDecode->nb_streams; i++) { 
     192        AVStream *ist = pFormatCtxDecode->streams[i]; 
     193        AVStream *ost = av_new_stream(pFormatCtxEncode, i); 
     194 
     195        if ((ist->codec->codec_type==CODEC_TYPE_VIDEO) && transcode_video) { 
     196            ost->codec = avcodec_alloc_context(); 
     197 
     198            ost->codec->bit_rate = videobitrate*1000; 
     199            ost->codec->width = ist->codec->width; 
     200            ost->codec->height = ist->codec->height; 
     201            if(!ost->codec->width) ost->codec->width=720; 
     202            if(!ost->codec->height) ost->codec->height=576; 
     203 
     204            ost->codec->gop_size = 10; // emit one intra frame every ten frames 
     205            ost->codec->max_b_frames=5; 
     206            if (vcodec == CODEC_ID_WMV2) { 
     207               ost->codec->max_b_frames=0; //WMV2 does not accept b-frames 
     208            } 
     209            ost->codec->pix_fmt = (PixelFormat) 0;//ist->codec->pix_fmt; 
     210 
     211            if(av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) && 
     212                    av_q2d(ist->time_base) < 1.0/1000) 
     213                ost->codec->time_base = ist->codec->time_base; 
     214            else 
     215                ost->codec->time_base = ist->time_base; 
     216 
     217 
     218            if (avcodec_open(ost->codec, pVideoCodecEncode) < 0) { 
     219                    fprintf(stderr, "could not open video codec!!!\n"); 
     220                    return; 
     221            } 
     222 
     223            AVCodec *pCodecDecode=avcodec_find_decoder(ist->codec->codec_id); 
     224            if(pCodecDecode==NULL) { 
     225                VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open video decoder!\n"); 
     226                return; 
     227            } 
     228 
     229            if(avcodec_open(ist->codec, pCodecDecode)<0) { 
     230                VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open video decoder!\n"); 
     231                return; 
     232            } 
     233 
     234 
     235        } 
     236        else if ((ist->codec->codec_type==CODEC_TYPE_AUDIO) && transcode_audio) { 
     237            ost->codec = avcodec_alloc_context(); 
     238            ost->codec->bit_rate = audiobitrate*1000; 
     239            ost->codec->me_method = ist->codec->me_method; 
     240            ost->codec->sample_fmt = ist->codec->sample_fmt; 
     241                            if(!ost->codec->width) ost->codec->width=720; 
     242                    if(!ost->codec->height) ost->codec->height=576; 
     243 
     244            //if(!ost->codec->codec_tag){ 
     245            //    if(  pFormatCtxEncode->oformat->codec_tag 
     246            //        || av_codec_get_id (pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_tag) > 0 
     247            //        || av_codec_get_tag(pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_id) <= 0) 
     248            //        ost->codec->codec_tag = ist->codec->codec_tag; 
     249            //} 
     250 
     251            ost->codec->extradata = ist->codec->extradata; 
     252            ost->codec->extradata_size = ist->codec->extradata_size; 
     253 
     254 
     255 
     256            if(av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) && 
     257                    av_q2d(ist->time_base) < 1.0/1000) 
     258                ost->codec->time_base = ist->codec->time_base; 
     259            else 
     260                ost->codec->time_base = ist->time_base; 
     261 
     262            ost->codec->sample_rate = 48000; 
     263            ost->codec->channels = ist->codec->channels?ist->codec->channels:2; 
     264            ost->codec->block_align= 0; 
     265 
     266            if (avcodec_open(ost->codec, pAudioCodecEncode) < 0) { 
     267                    fprintf(stderr, "could not open audio codec!!!\n"); 
     268                    return; 
     269            } 
     270 
     271            AVCodec *pCodecDecode=avcodec_find_decoder(ist->codec->codec_id); 
     272            if(pCodecDecode==NULL) { 
     273                VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open audio decoder!\n"); 
     274                return; 
     275            } 
     276 
     277            if(avcodec_open(ist->codec, pCodecDecode)<0) { 
     278                VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open audio decoder!\n"); 
     279                return; 
     280            } 
     281 
     282 
     283        } 
     284        else { 
     285            ost->stream_copy=1; 
     286            ost->codec->codec_id = ist->codec->codec_id; 
     287            ost->codec->codec_type = ist->codec->codec_type; 
     288            ost->codec->codec_tag = ist->codec->codec_tag; 
     289            memcpy(ost->codec->codec_name,ist->codec->codec_name,sizeof(ost->codec->codec_name)); 
     290            ost->codec->sub_id = ist->codec->sub_id; 
     291            ost->codec->me_method = ist->codec->me_method; 
     292            ost->codec->sample_fmt = ist->codec->sample_fmt; 
     293 
     294            //if(!ost->codec->codec_tag){ 
     295            //    if(  pFormatCtxEncode->oformat->codec_tag 
     296            //        || av_codec_get_id (pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_tag) > 0 
     297            //        || av_codec_get_tag(pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_id) <= 0) 
     298            //        ost->codec->codec_tag = ist->codec->codec_tag; 
     299            //} 
     300 
     301            ost->codec->bit_rate = ist->codec->bit_rate; 
     302            ost->codec->extradata = ist->codec->extradata; 
     303            ost->codec->extradata_size = ist->codec->extradata_size; 
     304 
     305            if(av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) && 
     306                    av_q2d(ist->time_base) < 1.0/1000) 
     307                ost->codec->time_base = ist->codec->time_base; 
     308            else 
     309                ost->codec->time_base = ist->time_base; 
     310 
     311            switch(ost->codec->codec_type) { 
     312                case CODEC_TYPE_AUDIO: 
     313                    ost->codec->sample_rate = ist->codec->sample_rate?ist->codec->sample_rate:48000; 
     314                    ost->codec->channels = ist->codec->channels?ist->codec->channels:2; 
     315                    ost->codec->frame_size = ist->codec->frame_size; 
     316                    ost->codec->block_align= ist->codec->block_align; 
     317                    if(ost->codec->block_align == 1 && ost->codec->codec_id == CODEC_ID_MP3) 
     318                        ost->codec->block_align=0; 
     319                        break; 
     320                case CODEC_TYPE_VIDEO: 
     321                    ost->codec->pix_fmt = ist->codec->pix_fmt; 
     322                    ost->codec->width = ist->codec->width; 
     323                    ost->codec->height = ist->codec->height; 
     324                    ost->codec->has_b_frames = ist->codec->has_b_frames; 
     325                    if(!ost->codec->width) ost->codec->width=720; 
     326                    if(!ost->codec->height) ost->codec->height=576; 
     327                    break; 
     328                case CODEC_TYPE_SUBTITLE: 
     329                    break; 
     330                default: 
     331                    break; 
     332            } 
     333 
     334            ost->pts.num = ist->pts.num; 
     335            ost->pts.den = ist->pts.den; 
     336        } 
     337    } 
     338 
     339    //dump_format(pFormatCtxEncode, i, pFormatCtxEncode->filename, 1); 
     340    url_fopen (&pFormatCtxEncode->pb, pFormatCtxEncode->filename, URL_WRONLY); 
     341    av_write_header (pFormatCtxEncode); 
     342 
     343    AVFrame *pFrame = avcodec_alloc_frame(); 
     344    int frameFinished; 
     345    int outbuf_size = 100000; 
     346    uint8_t *outbuf = new uint8_t[outbuf_size]; 
     347    int audiosamplesize=AVCODEC_MAX_AUDIO_FRAME_SIZE; 
     348    int16_t *audiosample = new int16_t[audiosamplesize]; 
     349 
     350    //Copy or Transcode 
     351    while (av_read_frame(pFormatCtxDecode, &packet) >= 0) { 
     352        if (pFormatCtxEncode->streams[packet.stream_index]->stream_copy) { 
     353             if (av_write_frame (pFormatCtxEncode, &packet)) 
     354                VERBOSE(VB_RECORD, LOC + "Write frame failed!\n"); 
     355        } 
     356        else { 
     357            if (pFormatCtxDecode->streams[packet.stream_index]->codec->codec_type==CODEC_TYPE_VIDEO) { 
     358                avcodec_decode_video(pFormatCtxDecode->streams[packet.stream_index]->codec, pFrame, &frameFinished, packet.data, packet.size); 
     359                if(frameFinished) 
     360                { 
     361                     int out_size = avcodec_encode_video(pFormatCtxEncode->streams[packet.stream_index]->codec, outbuf, outbuf_size, (AVFrame*)pFrame); 
     362                    //printf("encoding frame %3d (size=%5d)\n", i, out_size); 
     363                    //AVPacket avpkt; 
     364                    //av_init_packet(&avpkt); 
     365                    //avpkt.stream_index = packet.stream_index; 
     366                    //avpkt.data=outbuf; 
     367                    //avpkt.size=out_size; 
     368                    //avpkt.dts = packet.dts; 
     369                    //avpkt.pts = packet.pts; 
     370                    packet.data=outbuf; 
     371                    packet.size=out_size; 
     372                    //avpkt.duration = packet.duration; 
     373                    av_write_frame(pFormatCtxEncode, &packet); 
     374                } 
     375            } 
     376            else { 
     377                audiosamplesize=AVCODEC_MAX_AUDIO_FRAME_SIZE; 
     378                avcodec_decode_audio2(pFormatCtxDecode->streams[packet.stream_index]->codec, audiosample, &audiosamplesize, packet.data, packet.size); 
     379                int out_size = avcodec_encode_audio( pFormatCtxEncode->streams[packet.stream_index]->codec, outbuf, outbuf_size, audiosample ); 
     380                packet.data=outbuf; 
     381                packet.size=out_size; 
     382                av_write_frame(pFormatCtxEncode, &packet); 
     383 
     384 
     385            } 
     386        } 
     387        //av_free_packet (&packet); 
     388    } 
     389    delete pFormatCtxEncode; 
     390    delete pFormatCtxDecode; 
     391    return; 
     392} 
  • mythtv/libs/libmythtv/dtvrecorder.cpp

     
    104104            VERBOSE(VB_IMPORTANT, LOC_ERR + 
    105105                    "Could not allocate new packet buffer."); 
    106106    } 
     107    else { 
     108       RecorderBase::SetOption(name, value); 
     109    } 
    107110} 
    108111 
    109112/** \fn DTVRecorder::FinishRecording(void) 
     
    116119    { 
    117120        if (_payload_buffer.size()) 
    118121        { 
    119             ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     122            if (doTranscode) { 
     123              transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     124            } 
     125            else { 
     126              ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     127            } 
    120128            _payload_buffer.clear(); 
    121129        } 
    122         ringBuffer->WriterFlush(); 
     130        if (doTranscode) { 
     131          transcoder->ringBuffer->SetEOF(); 
     132        } 
     133        else { 
     134          ringBuffer->WriterFlush(); 
     135        } 
    123136    } 
    124137 
    125138    if (curRecording) 
     
    193206    // we have to write them first... 
    194207    if (!_payload_buffer.empty()) 
    195208    { 
    196         if (ringBuffer) 
    197             ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     209        if (doTranscode) { 
     210          transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     211        } 
     212        else { 
     213          ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     214        } 
    198215        _payload_buffer.clear(); 
    199216    } 
    200217 
    201218    if (ringBuffer) 
    202         ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 
     219       if (doTranscode) { 
     220           transcoder->ringBuffer->Write((unsigned char*)tspacket.data(), TSPacket::SIZE); 
     221         } 
     222         else { 
     223           ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 
     224         } 
     225 
    203226} 
    204227 
    205228/** \fn DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) 
     
    401424    SavePositionMap(true); 
    402425    if (ringBuffer) 
    403426    { 
    404         ringBuffer->WriterFlush(); 
     427        if (doTranscode) { 
     428            transcoder->ringBuffer->SetEOF(); 
     429        } 
     430        else { 
     431            ringBuffer->WriterFlush(); 
     432        } 
    405433        if (curRecording) 
    406434            curRecording->SetFilesize(ringBuffer->GetRealFileSize()); 
    407435    } 
     
    736764            { 
    737765                if (ringBuffer) 
    738766                { 
    739                     ringBuffer->Write( 
    740                         &_payload_buffer[0], _payload_buffer.size()); 
     767                    if (doTranscode) { 
     768                        transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     769                    } 
     770                    else { 
     771                        ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
     772                    } 
     773 
    741774                } 
    742775                _payload_buffer.clear(); 
    743776            } 
    744777 
    745778            if (ringBuffer) 
    746                 ringBuffer->Write(bufstart, (bufptr - bufstart)); 
     779                if (doTranscode) { 
     780                    transcoder->ringBuffer->Write((unsigned char*)bufstart, (bufptr - bufstart)); 
     781                } 
     782                else { 
     783                    ringBuffer->Write(bufstart, (bufptr - bufstart)); 
     784                } 
    747785 
    748786            bufstart = bufptr; 
    749787        } 
  • mythtv/libs/libmythtv/recorderbase.h

     
    1111#include <pthread.h> 
    1212 
    1313#include "mythexp.h" 
     14#include "transcoder.h" 
    1415 
    1516class TVRec; 
    1617class RingBuffer; 
     
    257258    bool           weMadeBuffer; 
    258259 
    259260    QString        videocodec; 
     261    QString        audiocodec; 
    260262    QString        audiodevice; 
    261263    QString        videodevice; 
    262264    QString        vbidevice; 
    263265 
     266    int            videobitrate; 
     267    int            audiobitrate; 
    264268    int            vbimode; 
    265269    bool           ntsc; 
    266270    bool           ntsc_framerate; 
     
    290294    PosMap         positionMap; 
    291295    PosMap         positionMapDelta; 
    292296 
     297    //Transcode 
     298    bool           doTranscode; 
     299    Transcoder    *transcoder; 
     300 
    293301}; 
    294302 
    295303#endif 
  • mythtv/libs/libmythtv/RealRingBuffer.h

     
     1#ifndef REALRINGBUFFER_H 
     2#define REALRINGBUFFER_H 
     3 
     4#include <qthread.h> 
     5#include <qmutex.h> 
     6#include <qwaitcondition.h> 
     7 
     8using namespace std; 
     9 
     10class RealRingBuffer { 
     11public: 
     12  RealRingBuffer( int size ); 
     13  ~RealRingBuffer(); 
     14  int Write( unsigned char *buf, int len ); 
     15  int Read( unsigned char *buf, int len ); 
     16  void SetEOF(); 
     17  bool IsEOF(); 
     18private: 
     19  char *rb; 
     20  int rbsize; 
     21  int rbrpos; 
     22  int rbwpos; 
     23  int bytes; 
     24  bool eof; 
     25  QMutex mutex; 
     26  QWaitCondition needData; 
     27  QWaitCondition needSpace; 
     28}; 
     29 
     30#endif 
  • mythtv/libs/libmythtv/recordingprofile.cpp

     
    528528    }; 
    529529}; 
    530530 
     531 
     532class VideoBitrate : public SliderSetting, public CodecParamStorage 
     533{ 
     534  public: 
     535    VideoBitrate(const RecordingProfile &parent) : 
     536        SliderSetting(this, 100, 8000, 100), 
     537        CodecParamStorage(this, parent, "videobitrate") 
     538    { 
     539        setLabel(QObject::tr("Video Bitrate")); 
     540        setValue(2200); 
     541        setHelpText(QObject::tr("Bitrate in kilobits/second.  2200Kbps is " 
     542                    "approximately 1 Gigabyte per hour.")); 
     543    }; 
     544}; 
     545 
     546class AudioBitrate : public SliderSetting, public CodecParamStorage 
     547{ 
     548  public: 
     549    AudioBitrate(const RecordingProfile &parent) : 
     550        SliderSetting(this, 32, 320, 16), 
     551        CodecParamStorage(this, parent, "audiobitrate") 
     552    { 
     553        setLabel(QObject::tr("Audio Bitrate")); 
     554        setValue(2200); 
     555        setHelpText(QObject::tr("Bitrate in kilobits/second.")); 
     556    }; 
     557}; 
     558 
     559class VideoCodec : public ComboBoxSetting, public CodecParamStorage 
     560{ 
     561  public: 
     562    VideoCodec(const RecordingProfile &parent) : 
     563        ComboBoxSetting(this), 
     564        CodecParamStorage(this, parent, "videocodec") 
     565    { 
     566        setLabel(QObject::tr("Video Codec")); 
     567 
     568        addSelection("mpeg2"); 
     569        addSelection("mpeg4"); 
     570        addSelection("wmv2"); 
     571        setValue(0); 
     572        setHelpText(QObject::tr("Sets the video codec.")); 
     573    }; 
     574}; 
     575 
     576class AudioCodec : public ComboBoxSetting, public CodecParamStorage 
     577{ 
     578  public: 
     579    AudioCodec(const RecordingProfile &parent) : 
     580        ComboBoxSetting(this), 
     581        CodecParamStorage(this, parent, "audiocodec") 
     582    { 
     583        setLabel(QObject::tr("Audio Codec")); 
     584 
     585        addSelection("mp2"); 
     586        addSelection("wmav2"); 
     587 
     588        setValue(0); 
     589        setHelpText(QObject::tr("Sets the audio codec.")); 
     590    }; 
     591}; 
     592 
     593 
     594class Transcode : public CheckBoxSetting, public CodecParamStorage 
     595{ 
     596  public: 
     597    Transcode(const RecordingProfile &parent) : 
     598        CheckBoxSetting(this), 
     599        CodecParamStorage(this, parent, "transcode") 
     600    { 
     601        setLabel(QObject::tr("Enable transcoding")); 
     602        setValue(true); 
     603        setHelpText(QObject::tr("If set, transcoding gets enabled.")); 
     604    }; 
     605}; 
     606 
     607 
    531608class ScaleBitrate : public CheckBoxSetting, public CodecParamStorage 
    532609{ 
    533610  public: 
     
    795872    }; 
    796873}; 
    797874 
     875class TranscoderSettings : public TriggeredConfigurationGroup 
     876{ 
     877  public: 
     878    TranscoderSettings(const RecordingProfile &parent, QString profName) : 
     879        TriggeredConfigurationGroup(false, true, false, false) 
     880    { 
     881        QString labelName; 
     882        labelName = QObject::tr("Transcoder"); 
     883        setName(labelName); 
     884 
     885        transcode = new Transcode(parent); 
     886        addChild(transcode); 
     887        setTrigger(transcode); 
     888 
     889        ConfigurationGroup* params = new VerticalConfigurationGroup(); 
     890        params->setLabel(QObject::tr("Video Parameters")); 
     891        params->addChild(new VideoCodec(parent)); 
     892        params->addChild(new VideoBitrate(parent)); 
     893 
     894        //addTarget("transcode", params); 
     895 
     896        //params = new VerticalConfigurationGroup(); 
     897        //params->setLabel(QObject::tr("Audio Parameters")); 
     898        params->addChild(new AudioCodec(parent)); 
     899        params->addChild(new AudioBitrate(parent)); 
     900 
     901        addTarget("transcode", params); 
     902 
     903    } 
     904 
     905private: 
     906    Transcode* transcode; 
     907}; 
     908 
     909 
    798910class VideoCompressionSettings : public TriggeredConfigurationGroup 
    799911{ 
    800912  public: 
     
    12901402    else if (type.toUpper() == "DVB") 
    12911403    { 
    12921404        addChild(new RecordingType(*this)); 
     1405        addChild(new TranscoderSettings(*this, profileName)); 
    12931406    } 
    12941407 
    12951408    id->setValue(profileId); 
  • mythtv/libs/libmythtv/RealRingBuffer.cpp

     
     1#include "RealRingBuffer.h" 
     2#include "mythverbose.h" 
     3 
     4#define LOC QString("RealRingBuffer: ") 
     5#define LOC_ERR QString("RealRingBuffer Error: ") 
     6 
     7 
     8RealRingBuffer::RealRingBuffer(int size) { 
     9  rbsize=size; 
     10  eof=false; 
     11  rbrpos=0; 
     12  rbwpos=0; 
     13  bytes=0; 
     14  rb = new char[size]; 
     15} 
     16 
     17RealRingBuffer::~RealRingBuffer() { 
     18  delete rb; 
     19} 
     20 
     21bool RealRingBuffer::IsEOF() { 
     22  return eof; 
     23} 
     24 
     25void RealRingBuffer::SetEOF() { 
     26  QMutexLocker locker(&mutex); 
     27  eof=true; 
     28  needData.wakeAll(); 
     29} 
     30 
     31int RealRingBuffer::Read(unsigned char *buf, int size) { 
     32    int len = 0; 
     33 
     34    QMutexLocker locker(&mutex); 
     35 
     36    if (eof && bytes==0) { 
     37        return -1; 
     38    } 
     39 
     40    while (size>0) { 
     41 
     42        if (bytes==0) { 
     43            if (eof) { 
     44                return len; 
     45            } 
     46            needData.wait(&mutex); 
     47        } 
     48 
     49        int rby = bytes > size ? size : bytes; 
     50 
     51        if (rbrpos+rby>rbsize) { 
     52            rby = rbsize-rbrpos; 
     53        } 
     54 
     55        memcpy(buf, rb + rbrpos, rby); 
     56        size -= rby; 
     57        buf += rby; 
     58        bytes -= rby; 
     59        len += rby; 
     60        rbrpos = (rbrpos + rby)%rbsize; 
     61        needSpace.wakeAll(); 
     62    } 
     63    return len; 
     64} 
     65 
     66int RealRingBuffer::Write(unsigned char *buf, int size) { 
     67    int len = 0; 
     68    QMutexLocker locker(&mutex); 
     69 
     70    while (size>0) { 
     71 
     72        if (rbsize-bytes==0) { 
     73            VERBOSE(VB_RECORD, LOC + "Ringbuffer is full. Waiting for data read."); 
     74            needSpace.wait(&mutex); 
     75        } 
     76 
     77        int wb = rbsize-bytes>size ? size : rbsize-bytes; 
     78 
     79        if (rbwpos+wb>rbsize) { 
     80            wb = rbsize-rbwpos; 
     81        } 
     82 
     83        memcpy(rb+rbwpos,buf,wb); 
     84        size -= wb; 
     85        buf += wb; 
     86        bytes += wb; 
     87        len += wb; 
     88        rbwpos = (rbwpos + wb)%rbsize; 
     89        needData.wakeAll(); 
     90    } 
     91    return len; 
     92}