Ticket #6888: live_transcode.patch
| File live_transcode.patch, 31.2 KB (added by buehlmann@…, 3 years ago) |
|---|
-
mythtv/libs/libmythtv/dvbrecorder.cpp
156 156 SetOption("videodevice", videodev); 157 157 DTVRecorder::SetOption("tvformat", gContext->GetSetting("TVFormat")); 158 158 SetStrOption(profile, "recordingtype"); 159 SetIntOption(profile, "transcode"); 160 SetStrOption(profile, "videocodec"); 161 SetIntOption(profile, "videobitrate"); 162 SetStrOption(profile, "audiocodec"); 163 SetIntOption(profile, "audiobitrate"); 159 164 } 160 165 161 166 void DVBRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) … … 562 567 if (!_payload_buffer.empty()) 563 568 { 564 569 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 } 566 576 _payload_buffer.clear(); 567 577 } 568 578 569 579 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 } 571 586 } -
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> 14 using 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 24 class Transcoder : public QThread { 25 public: 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(); 33 private: 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
158 158 HEADERS += transporteditor.h listingsources.h 159 159 HEADERS += myth_imgconvert.h 160 160 HEADERS += channelgroup.h channelgroupsettings.h 161 HEADERS += RealRingBuffer.h transcoder.h 161 162 162 163 # Remove when everything is switched to MythUI 163 164 HEADERS += proglist_qt.h … … 183 184 SOURCES += transporteditor.cpp 184 185 SOURCES += channelgroup.cpp channelgroupsettings.cpp 185 186 SOURCES += myth_imgconvert.cpp 187 SOURCES += RealRingBuffer.cpp transcoder.cpp 186 188 187 189 # Remove when everything is switched to MythUI 188 190 SOURCES += proglist_qt.cpp -
mythtv/libs/libmythtv/dvbrecorder.h
123 123 unsigned char _continuity_counter[0x1fff + 1]; 124 124 vector<TSPacket> _scratch; 125 125 126 //Transcoding 127 Transcoder *tc; 128 126 129 // Statistics 127 130 mutable uint _continuity_error_count; 128 131 mutable uint _stream_overflow_count; -
mythtv/libs/libmythtv/recorderbase.cpp
32 32 vbimode(0), ntsc(true), ntsc_framerate(true), video_frame_rate(29.97), 33 33 m_videoAspect(0), m_videoHeight(0), m_videoWidth(0), curRecording(NULL), 34 34 request_pause(false), paused(false), nextRingBuffer(NULL), nextRecording(NULL), 35 positionMapType(MARK_GOP_BYFRAME), positionMapLock() 35 positionMapType(MARK_GOP_BYFRAME), positionMapLock(), doTranscode(false) 36 36 { 37 37 QMutexLocker locker(&avcodeclock); 38 38 avcodec_init(); // init CRC's … … 40 40 41 41 RecorderBase::~RecorderBase(void) 42 42 { 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 } 43 49 if (weMadeBuffer && ringBuffer) 44 50 { 45 51 delete ringBuffer; … … 61 67 msg = " '" + rbuf->GetFilename() + "'"; 62 68 VERBOSE(VB_RECORD, LOC + "SetRingBuffer("<<rbuf<<")"<<msg); 63 69 } 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 } 64 79 ringBuffer = rbuf; 65 80 weMadeBuffer = false; 66 81 } … … 87 102 { 88 103 if (name == "videocodec") 89 104 videocodec = value; 105 else if (name == "audiocodec") 106 audiocodec = value; 90 107 else if (name == "audiodevice") 91 108 audiodevice = value; 92 109 else if (name == "videodevice") … … 131 148 132 149 void RecorderBase::SetOption(const QString &name, int value) 133 150 { 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 + 135 159 QString("SetOption(): Unknown int option: %1: %2") 136 160 .arg(name).arg(value)); 137 161 } … … 139 163 void RecorderBase::SetIntOption(RecordingProfile *profile, const QString &name) 140 164 { 141 165 const Setting *setting = profile->byName(name); 142 if (setting) 166 if (setting) { 143 167 SetOption(name, setting->getValue().toInt()); 168 } 144 169 else 145 170 VERBOSE(VB_IMPORTANT, LOC_ERR + QString( 146 171 "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 10 extern "C" { 11 #include "libavcodec/avcodec.h" 12 #include "libavformat/avformat.h" 13 #include "libavformat/mpegts.h" 14 } 15 16 static 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 22 static 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 28 static 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 33 static int rb_close(URLContext *h) { 34 return 0; 35 } 36 37 38 static 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 44 static 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 50 static 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 55 static int rb1_close(URLContext *h) { 56 RingBuffer *rb = (RingBuffer *)h->priv_data; 57 rb->WriterFlush(); 58 return 0; 59 } 60 61 static int64_t rb1_seek(URLContext *h, int64_t os, int pos) { 62 return 0; 63 } 64 65 66 67 URLProtocol rb_protocol = { 68 "rb", 69 rb_open, 70 rb_read, 71 rb_write, 72 NULL, 73 rb_close, 74 }; 75 76 URLProtocol rb1_protocol = { 77 "rc", 78 rb1_open, 79 rb1_read, 80 rb1_write, 81 rb1_seek, 82 rb1_close, 83 }; 84 85 86 Transcoder::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 99 Transcoder::~Transcoder() { 100 delete ringBuffer; 101 } 102 103 void 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 114 void 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 144 void 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
104 104 VERBOSE(VB_IMPORTANT, LOC_ERR + 105 105 "Could not allocate new packet buffer."); 106 106 } 107 else { 108 RecorderBase::SetOption(name, value); 109 } 107 110 } 108 111 109 112 /** \fn DTVRecorder::FinishRecording(void) … … 116 119 { 117 120 if (_payload_buffer.size()) 118 121 { 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 } 120 128 _payload_buffer.clear(); 121 129 } 122 ringBuffer->WriterFlush(); 130 if (doTranscode) { 131 transcoder->ringBuffer->SetEOF(); 132 } 133 else { 134 ringBuffer->WriterFlush(); 135 } 123 136 } 124 137 125 138 if (curRecording) … … 193 206 // we have to write them first... 194 207 if (!_payload_buffer.empty()) 195 208 { 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 } 198 215 _payload_buffer.clear(); 199 216 } 200 217 201 218 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 203 226 } 204 227 205 228 /** \fn DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) … … 401 424 SavePositionMap(true); 402 425 if (ringBuffer) 403 426 { 404 ringBuffer->WriterFlush(); 427 if (doTranscode) { 428 transcoder->ringBuffer->SetEOF(); 429 } 430 else { 431 ringBuffer->WriterFlush(); 432 } 405 433 if (curRecording) 406 434 curRecording->SetFilesize(ringBuffer->GetRealFileSize()); 407 435 } … … 736 764 { 737 765 if (ringBuffer) 738 766 { 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 741 774 } 742 775 _payload_buffer.clear(); 743 776 } 744 777 745 778 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 } 747 785 748 786 bufstart = bufptr; 749 787 } -
mythtv/libs/libmythtv/recorderbase.h
11 11 #include <pthread.h> 12 12 13 13 #include "mythexp.h" 14 #include "transcoder.h" 14 15 15 16 class TVRec; 16 17 class RingBuffer; … … 257 258 bool weMadeBuffer; 258 259 259 260 QString videocodec; 261 QString audiocodec; 260 262 QString audiodevice; 261 263 QString videodevice; 262 264 QString vbidevice; 263 265 266 int videobitrate; 267 int audiobitrate; 264 268 int vbimode; 265 269 bool ntsc; 266 270 bool ntsc_framerate; … … 290 294 PosMap positionMap; 291 295 PosMap positionMapDelta; 292 296 297 //Transcode 298 bool doTranscode; 299 Transcoder *transcoder; 300 293 301 }; 294 302 295 303 #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 8 using namespace std; 9 10 class RealRingBuffer { 11 public: 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(); 18 private: 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
528 528 }; 529 529 }; 530 530 531 532 class 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 546 class 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 559 class 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 576 class 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 594 class 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 531 608 class ScaleBitrate : public CheckBoxSetting, public CodecParamStorage 532 609 { 533 610 public: … … 795 872 }; 796 873 }; 797 874 875 class 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 905 private: 906 Transcode* transcode; 907 }; 908 909 798 910 class VideoCompressionSettings : public TriggeredConfigurationGroup 799 911 { 800 912 public: … … 1290 1402 else if (type.toUpper() == "DVB") 1291 1403 { 1292 1404 addChild(new RecordingType(*this)); 1405 addChild(new TranscoderSettings(*this, profileName)); 1293 1406 } 1294 1407 1295 1408 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 8 RealRingBuffer::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 17 RealRingBuffer::~RealRingBuffer() { 18 delete rb; 19 } 20 21 bool RealRingBuffer::IsEOF() { 22 return eof; 23 } 24 25 void RealRingBuffer::SetEOF() { 26 QMutexLocker locker(&mutex); 27 eof=true; 28 needData.wakeAll(); 29 } 30 31 int 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 66 int 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 }
