Ticket #6888: live_transcode.2.patch
File live_transcode.2.patch, 36.6 KB (added by , 15 years ago) |
---|
-
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 { 572 transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 573 } 574 else 575 { 576 ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 577 } 566 578 _payload_buffer.clear(); 567 579 } 568 580 569 581 if (ringBuffer) 570 ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 582 if (doTranscode) 583 { 584 transcoder->ringBuffer->Write((unsigned char*)tspacket.data(), TSPacket::SIZE); 585 } 586 else 587 { 588 ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 589 } 571 590 } -
libs/libmythtv/avformatdecoder.cpp
1185 1185 1186 1186 if (stream->sample_aspect_ratio.num) 1187 1187 aspect_ratio = av_q2d(stream->sample_aspect_ratio); 1188 else if (enc->sample_aspect_ratio.num == 0)1188 else if (enc->sample_aspect_ratio.num) 1189 1189 aspect_ratio = av_q2d(enc->sample_aspect_ratio); 1190 1190 else 1191 1191 aspect_ratio = 1.0f; -
libs/libmythtv/transcoder.h
1 // -*- Mode: c++ -*- 2 /* 3 * Copyright (C) Rene Buehlmann 2009 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 { 26 public: 27 Transcoder(RingBuffer *output, std::string a = "Transcoder"); 28 ~Transcoder(); 29 void setParam(const QString &name, const QString &value); 30 void setParam(const QString &name, int value); 31 int Write(unsigned char *buf, int len); 32 RealRingBuffer *ringBuffer; 33 virtual void run(); 34 private: 35 std::string name; 36 RingBuffer *rb; 37 CodecID vcodec; 38 CodecID acodec; 39 int videobitrate; 40 int audiobitrate; 41 int width; 42 int height; 43 bool transcode_audio; 44 bool transcode_video; 45 }; 46 47 #endif 48 -
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 -
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; -
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 { 45 VERBOSE(VB_RECORD, LOC + "Waiting for transcoder to finish..."); 46 transcoder->wait(); 47 VERBOSE(VB_RECORD, LOC + "Transcoder finished!"); 48 delete transcoder; 49 transcoder = NULL; 50 } 43 51 if (weMadeBuffer && ringBuffer) 44 52 { 45 53 delete ringBuffer; … … 61 69 msg = " '" + rbuf->GetFilename() + "'"; 62 70 VERBOSE(VB_RECORD, LOC + "SetRingBuffer("<<rbuf<<")"<<msg); 63 71 } 72 if (doTranscode) 73 { 74 VERBOSE(VB_RECORD, LOC + "Start transcoder"); 75 transcoder = new Transcoder(rbuf, "TC"); 76 transcoder->setParam("videocodec", videocodec); 77 transcoder->setParam("audiocodec", audiocodec); 78 transcoder->setParam("videobitrate", videobitrate); 79 transcoder->setParam("audiobitrate", audiobitrate); 80 transcoder->start(); 81 } 64 82 ringBuffer = rbuf; 65 83 weMadeBuffer = false; 66 84 } … … 87 105 { 88 106 if (name == "videocodec") 89 107 videocodec = value; 108 else if (name == "audiocodec") 109 audiocodec = value; 90 110 else if (name == "audiodevice") 91 111 audiodevice = value; 92 112 else if (name == "videodevice") … … 131 151 132 152 void RecorderBase::SetOption(const QString &name, int value) 133 153 { 134 VERBOSE(VB_IMPORTANT, LOC_ERR + 154 if (name == "videobitrate") 155 videobitrate = value; 156 else if (name == "audiobitrate") 157 audiobitrate = value; 158 else if (name == "transcode") 159 doTranscode = value; 160 else 161 VERBOSE(VB_IMPORTANT, LOC_ERR + 135 162 QString("SetOption(): Unknown int option: %1: %2") 136 163 .arg(name).arg(value)); 137 164 } … … 227 254 ResetForNewFile(); 228 255 229 256 m_videoAspect = m_videoWidth = m_videoHeight = 0; 230 257 258 if (doTranscode) 259 { 260 VERBOSE(VB_RECORD, LOC + "Waiting for transcoder to finish..."); 261 transcoder->wait(); 262 VERBOSE(VB_RECORD, LOC + "Transcoder finished!"); 263 delete transcoder; 264 transcoder = NULL; 265 } 266 231 267 if (weMadeBuffer && ringBuffer) 232 268 delete ringBuffer; 233 269 SetRingBuffer(nextRingBuffer); -
libs/libmythtv/transcoder.cpp
1 // -*- Mode: c++ -*- 2 /* 3 * Copyright (C) Rene Buehlmann 2009 4 * 5 * Copyright notice is in dvbrecorder.cpp of the MythTV project. 6 */ 7 8 #include "transcoder.h" 9 #include "mythverbose.h" 10 #include "format.h" 11 #include <stdio.h> 12 #include <string.h> 13 14 #define LOC QString("Transcoder: ") 15 #define LOC_ERR QString("Transcoder Error: ") 16 17 // AVLib/FFMPEG includes 18 extern "C" 19 { 20 #include "libavcodec/avcodec.h" 21 #include "libavformat/avformat.h" 22 #include "libavformat/mpegts.h" 23 #include "libswscale/swscale.h" 24 } 25 26 static int rb_open(URLContext *h, const char *filename, int flags) 27 { 28 h->priv_data = (char *) strtoul(filename + 3, NULL, 16); 29 h->is_streamed = true; 30 return 0; 31 } 32 33 static int rb_read(URLContext *h, unsigned char *buf, int size) 34 { 35 RealRingBuffer *rb = (RealRingBuffer *) h->priv_data; 36 int len = rb->Read(buf, size); 37 return len; 38 } 39 40 static int rb_write(URLContext *h, unsigned char *buf, int size) 41 { 42 RealRingBuffer *rb = (RealRingBuffer *) h->priv_data; 43 return rb->Write(buf, size); 44 } 45 46 static int rb_close(URLContext *h) 47 { 48 return 0; 49 } 50 51 static int rb1_open(URLContext *h, const char *filename, int flags) 52 { 53 h->priv_data = (char *) strtoul(filename + 3, NULL, 16); 54 h->is_streamed = true; 55 return 0; 56 } 57 58 static int rb1_read(URLContext *h, unsigned char *buf, int size) 59 { 60 RingBuffer *rb = (RingBuffer *) h->priv_data; 61 int len = rb->Read(buf, size); 62 return len; 63 } 64 65 static int rb1_write(URLContext *h, unsigned char *buf, int size) 66 { 67 RingBuffer *rb = (RingBuffer *) h->priv_data; 68 return rb->Write(buf, size); 69 } 70 71 static int rb1_close(URLContext *h) 72 { 73 RingBuffer *rb = (RingBuffer *) h->priv_data; 74 rb->WriterFlush(); 75 return 0; 76 } 77 78 static int64_t rb1_seek(URLContext *h, int64_t os, int pos) 79 { 80 return 0; 81 } 82 83 URLProtocol rb_protocol = 84 { "rb", rb_open, rb_read, rb_write, NULL, rb_close, }; 85 86 URLProtocol rb1_protocol = 87 { "rc", rb1_open, rb1_read, rb1_write, rb1_seek, rb1_close, }; 88 89 Transcoder::Transcoder(RingBuffer *rb1, std::string a) : 90 name(a) 91 { 92 av_register_all(); 93 register_protocol(&rb_protocol); 94 register_protocol(&rb1_protocol); 95 ringBuffer = new RealRingBuffer(1024* 1024 ); //Let's try it with 1 MB... We might need to increase this. 96 rb = rb1; 97 vcodec = CODEC_ID_MPEG2VIDEO; 98 acodec = CODEC_ID_MP2; 99 transcode_video=true; 100 transcode_audio=true; 101 } 102 103 Transcoder::~Transcoder() 104 { 105 delete ringBuffer; 106 } 107 108 void Transcoder::setParam(const QString &name, int value) 109 { 110 if (name == "videobitrate") 111 { 112 videobitrate = value; 113 } 114 else if (name == "height") 115 { 116 height = value; 117 } 118 else if (name == "width") 119 { 120 width = value; 121 } 122 else if (name == "audiobitrate") 123 { 124 audiobitrate = value; 125 } 126 } 127 128 void Transcoder::setParam(const QString &name, const QString &value) 129 { 130 if (name == "videocodec") 131 { 132 if (value == "mpeg4") 133 { 134 vcodec = CODEC_ID_MPEG4; 135 } 136 else if (value == "wmv2") 137 { 138 vcodec = CODEC_ID_WMV2; 139 } 140 else if (value == "mpeg2") 141 { 142 vcodec = CODEC_ID_MPEG2VIDEO; 143 } 144 else 145 { 146 transcode_video = false; 147 } 148 } 149 else if (name == "audiocodec") 150 { 151 if (value == "mp2") 152 { 153 acodec = CODEC_ID_MP2; 154 } 155 if (value == "wmav2") 156 { 157 acodec = CODEC_ID_WMAV2; 158 } 159 else 160 { 161 transcode_audio = false; 162 } 163 } 164 } 165 166 void Transcoder::run() 167 { 168 int i; 169 AVPacket packet; 170 AVFormatContext *pFormatCtxDecode; 171 AVFormatContext *pFormatCtxEncode; 172 SwsContext *scaleContext; 173 174 // Open video 175 char buf[30]; 176 sprintf((char *) &buf, "rb:%p", ringBuffer); 177 if (av_open_input_file(&pFormatCtxDecode, (char *) &buf, NULL, 0, NULL) 178 != 0) 179 { 180 return; // Couldn't open file 181 } 182 183 // Retrieve stream information 184 if (av_find_stream_info(pFormatCtxDecode) < 0) 185 return; // Couldn't find stream information 186 187 // Dump information about file onto standard error 188 dump_format(pFormatCtxDecode, 0, (char *) &buf, false); 189 pFormatCtxDecode->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX 190 | AVFMT_NOTIMESTAMPS; 191 192 //Prepare Output 193 pFormatCtxEncode = av_alloc_format_context(); 194 pFormatCtxEncode->oformat = guess_format("mpegts", NULL, NULL); 195 pFormatCtxEncode->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX 196 | AVFMT_NOTIMESTAMPS; 197 sprintf((char *) &buf, "rc:%p", rb); 198 memcpy(pFormatCtxEncode->filename, (char *) &buf, 199 sizeof(pFormatCtxEncode->filename)); 200 201 //Prepare Video Codec 202 AVCodec *pVideoCodecEncode = avcodec_find_encoder(vcodec); 203 if (pVideoCodecEncode == NULL) 204 { 205 VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open video encoder!\n"); 206 return; 207 } 208 209 //Prepare Audio Codec 210 AVCodec *pAudioCodecEncode = avcodec_find_encoder(acodec); 211 if (pAudioCodecEncode == NULL) 212 { 213 VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open audio encoder!\n"); 214 return; 215 } 216 217 // Copy the streams 218 for (i = 0; i < pFormatCtxDecode->nb_streams; i++) 219 { 220 AVStream *ist = pFormatCtxDecode->streams[i]; 221 AVStream *ost = av_new_stream(pFormatCtxEncode, i); 222 223 if ((ist->codec->codec_type == CODEC_TYPE_VIDEO) && transcode_video) 224 { 225 ost->codec = avcodec_alloc_context(); 226 ost->codec->codec_type = ist->codec->codec_type; 227 ost->codec->bit_rate = videobitrate * 1000; 228 ost->codec->ildct_cmp = ist->codec->ildct_cmp; 229 ost->codec->sample_aspect_ratio.num 230 = ist->codec->sample_aspect_ratio.num; 231 ost->codec->sample_aspect_ratio.den 232 = ist->codec->sample_aspect_ratio.den; 233 ost->sample_aspect_ratio.num = ist->codec->sample_aspect_ratio.num; 234 ost->sample_aspect_ratio.den = ist->codec->sample_aspect_ratio.den; 235 ost->codec->width = ist->codec->width; 236 ost->codec->height = ist->codec->height; 237 if (!ost->codec->width) 238 ost->codec->width = 720; 239 if (!ost->codec->height) 240 ost->codec->height = 576; 241 ost->codec->pix_fmt = ist->codec->pix_fmt; 242 243 if (height != 0 && width != 0 && (ost->codec->width != width 244 || ost->codec->height != height)) 245 { 246 ost->codec->width = width; 247 ost->codec->height = height; 248 scaleContext = sws_getContext(ist->codec->width, 249 ist->codec->height, ist->codec->pix_fmt, width, height, 250 ost->codec->pix_fmt, 1, NULL, NULL, NULL); 251 if (!scaleContext) 252 { 253 VERBOSE(VB_IMPORTANT, LOC_ERR 254 + "Could not create scale context!\n"); 255 return; 256 } 257 } 258 259 ost->codec->gop_size = 10; // emit one intra frame every ten frames 260 ost->codec->max_b_frames = 5; 261 if (vcodec == CODEC_ID_WMV2) 262 { 263 ost->codec->max_b_frames = 0; //WMV2 does not accept b-frames 264 } 265 266 //if(av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) && 267 // av_q2d(ist->time_base) < 1.0/1000) 268 // ost->codec->time_base = ist->codec->time_base; 269 //else 270 //ost->codec->time_base = ist->codec->time_base; 271 //ost->time_base = ist->codec->time_base; 272 //fixed framerate for now 273 ost->time_base.num=1; 274 ost->time_base.den=25; 275 ost->codec->time_base.num=1; 276 ost->codec->time_base.den=25; 277 278 if (avcodec_open(ost->codec, pVideoCodecEncode) < 0) 279 { 280 fprintf(stderr, "could not open video codec!!!\n"); 281 return; 282 } 283 284 AVCodec *pCodecDecode = avcodec_find_decoder(ist->codec->codec_id); 285 if (pCodecDecode == NULL) 286 { 287 VERBOSE(VB_IMPORTANT, LOC_ERR 288 + "Could not open video decoder!\n"); 289 return; 290 } 291 292 if (avcodec_open(ist->codec, pCodecDecode) < 0) 293 { 294 VERBOSE(VB_IMPORTANT, LOC_ERR 295 + "Could not open video decoder!\n"); 296 return; 297 } 298 299 } 300 else if ((ist->codec->codec_type == CODEC_TYPE_AUDIO) 301 && transcode_audio) 302 { 303 ost->codec = avcodec_alloc_context(); 304 ost->codec->codec_type = ist->codec->codec_type; 305 ost->codec->bit_rate = audiobitrate * 1000; 306 ost->codec->me_method = ist->codec->me_method; 307 ost->codec->sample_fmt = ist->codec->sample_fmt; 308 if (!ost->codec->width) 309 ost->codec->width = 720; 310 if (!ost->codec->height) 311 ost->codec->height = 576; 312 313 //if(!ost->codec->codec_tag){ 314 // if( pFormatCtxEncode->oformat->codec_tag 315 // || av_codec_get_id (pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_tag) > 0 316 // || av_codec_get_tag(pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_id) <= 0) 317 // ost->codec->codec_tag = ist->codec->codec_tag; 318 //} 319 320 ost->codec->extradata = ist->codec->extradata; 321 ost->codec->extradata_size = ist->codec->extradata_size; 322 323 if (av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) 324 && av_q2d(ist->time_base) < 1.0 / 1000) 325 ost->codec->time_base = ist->codec->time_base; 326 else 327 ost->codec->time_base = ist->time_base; 328 329 ost->codec->sample_rate = 48000; 330 ost->codec->channels = ist->codec->channels ? ist->codec->channels 331 : 2; 332 ost->codec->block_align = 0; 333 334 if (avcodec_open(ost->codec, pAudioCodecEncode) < 0) 335 { 336 fprintf(stderr, "could not open audio codec!!!\n"); 337 return; 338 } 339 340 AVCodec *pCodecDecode = avcodec_find_decoder(ist->codec->codec_id); 341 if (pCodecDecode == NULL) 342 { 343 VERBOSE(VB_IMPORTANT, LOC_ERR 344 + "Could not open audio decoder!\n"); 345 return; 346 } 347 348 if (avcodec_open(ist->codec, pCodecDecode) < 0) 349 { 350 VERBOSE(VB_IMPORTANT, LOC_ERR 351 + "Could not open audio decoder!\n"); 352 return; 353 } 354 355 } 356 else 357 { 358 ost->stream_copy = 1; 359 ost->codec->codec_id = ist->codec->codec_id; 360 ost->codec->codec_type = ist->codec->codec_type; 361 ost->codec->codec_tag = ist->codec->codec_tag; 362 memcpy(ost->codec->codec_name, ist->codec->codec_name, 363 sizeof(ost->codec->codec_name)); 364 ost->codec->sub_id = ist->codec->sub_id; 365 ost->codec->me_method = ist->codec->me_method; 366 ost->codec->sample_fmt = ist->codec->sample_fmt; 367 368 //if(!ost->codec->codec_tag){ 369 // if( pFormatCtxEncode->oformat->codec_tag 370 // || av_codec_get_id (pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_tag) > 0 371 // || av_codec_get_tag(pFormatCtxEncode->oformat->codec_tag, ist->codec->codec_id) <= 0) 372 // ost->codec->codec_tag = ist->codec->codec_tag; 373 //} 374 375 ost->codec->bit_rate = ist->codec->bit_rate; 376 ost->codec->extradata = ist->codec->extradata; 377 ost->codec->extradata_size = ist->codec->extradata_size; 378 379 if (av_q2d(ist->codec->time_base) > av_q2d(ist->time_base) 380 && av_q2d(ist->time_base) < 1.0 / 1000) 381 ost->codec->time_base = ist->codec->time_base; 382 else 383 ost->codec->time_base = ist->time_base; 384 385 switch (ost->codec->codec_type) 386 { 387 case CODEC_TYPE_AUDIO: 388 ost->codec->sample_rate 389 = ist->codec->sample_rate ? ist->codec->sample_rate 390 : 48000; 391 ost->codec->channels 392 = ist->codec->channels ? ist->codec->channels : 2; 393 ost->codec->frame_size = ist->codec->frame_size; 394 ost->codec->block_align = ist->codec->block_align; 395 if (ost->codec->block_align == 1 && ost->codec->codec_id 396 == CODEC_ID_MP3) 397 ost->codec->block_align = 0; 398 break; 399 case CODEC_TYPE_VIDEO: 400 ost->codec->pix_fmt = ist->codec->pix_fmt; 401 ost->codec->width = ist->codec->width; 402 ost->codec->height = ist->codec->height; 403 ost->codec->has_b_frames = ist->codec->has_b_frames; 404 if (!ost->codec->width) 405 ost->codec->width = 720; 406 if (!ost->codec->height) 407 ost->codec->height = 576; 408 break; 409 case CODEC_TYPE_SUBTITLE: 410 break; 411 default: 412 break; 413 } 414 415 ost->pts.num = ist->pts.num; 416 ost->pts.den = ist->pts.den; 417 } 418 } 419 420 dump_format(pFormatCtxEncode, i, pFormatCtxEncode->filename, 1); 421 url_fopen(&pFormatCtxEncode->pb, pFormatCtxEncode->filename, URL_WRONLY); 422 av_write_header(pFormatCtxEncode); 423 424 AVFrame *pFrame = avcodec_alloc_frame(); 425 AVFrame *newFrame = pFrame; 426 int frameFinished; 427 int outbuf_size = 100000; 428 uint8_t *outbuf = new uint8_t[outbuf_size]; 429 int audiosamplesize = AVCODEC_MAX_AUDIO_FRAME_SIZE; 430 int16_t *audiosample = new int16_t[audiosamplesize]; 431 432 //For scaling 433 AVPicture *newPicture; 434 uint8_t *buffer; 435 if (scaleContext) 436 { 437 int numBytes = avpicture_get_size( 438 pFormatCtxEncode->streams[0]->codec->pix_fmt, width, height); 439 buffer = new uint8_t[numBytes]; 440 memset(buffer, 0, numBytes); 441 newPicture = new AVPicture(); 442 newFrame = avcodec_alloc_frame(); 443 avpicture_fill((AVPicture *) newPicture, buffer, 444 pFormatCtxEncode->streams[0]->codec->pix_fmt, width, height); 445 } 446 447 //Copy or Transcode 448 while (av_read_frame(pFormatCtxDecode, &packet) >= 0) 449 { 450 //only two streams for now.. 451 if (packet.stream_index > 2) 452 { 453 continue; 454 } 455 if (pFormatCtxEncode->streams[packet.stream_index]->stream_copy) 456 { 457 if (av_write_frame(pFormatCtxEncode, &packet)) 458 VERBOSE(VB_RECORD, LOC + "Write frame failed!\n"); 459 } 460 else 461 { 462 if (pFormatCtxDecode->streams[packet.stream_index]->codec->codec_type 463 == CODEC_TYPE_VIDEO) 464 { 465 avcodec_decode_video( 466 pFormatCtxDecode->streams[packet.stream_index]->codec, 467 pFrame, &frameFinished, packet.data, packet.size); 468 if (frameFinished) 469 { 470 //Do rescale? 471 if (scaleContext) 472 { 473 sws_scale( 474 scaleContext, 475 pFrame->data, 476 pFrame->linesize, 477 0, 478 pFormatCtxDecode->streams[packet.stream_index]->codec->height, 479 newPicture->data, newPicture->linesize); 480 newFrame->data[0] = newPicture->data[0]; 481 newFrame->linesize[0] = newPicture->linesize[0]; 482 newFrame->data[1] = newPicture->data[1]; 483 newFrame->linesize[1] = newPicture->linesize[1]; 484 newFrame->data[2] = newPicture->data[2]; 485 newFrame->linesize[2] = newPicture->linesize[2]; 486 newFrame->data[3] = newPicture->data[3]; 487 newFrame->linesize[3] = newPicture->linesize[3]; 488 } 489 490 int 491 out_size = 492 avcodec_encode_video( 493 pFormatCtxEncode->streams[packet.stream_index]->codec, 494 outbuf, outbuf_size, 495 (AVFrame*) newFrame); 496 packet.data = outbuf; 497 packet.size = out_size; 498 av_write_frame(pFormatCtxEncode, &packet); 499 } 500 } 501 else 502 { 503 audiosamplesize = AVCODEC_MAX_AUDIO_FRAME_SIZE; 504 avcodec_decode_audio2( 505 pFormatCtxDecode->streams[packet.stream_index]->codec, 506 audiosample, &audiosamplesize, packet.data, packet.size); 507 int out_size = avcodec_encode_audio( 508 pFormatCtxEncode->streams[packet.stream_index]->codec, 509 outbuf, outbuf_size, audiosample); 510 packet.data = outbuf; 511 packet.size = out_size; 512 av_write_frame(pFormatCtxEncode, &packet); 513 514 } 515 } 516 } 517 if (scaleContext) 518 { 519 sws_freeContext(scaleContext); 520 delete buffer; 521 delete newPicture; 522 } 523 av_free_packet(&packet); 524 delete pFrame; 525 delete pFormatCtxEncode; 526 delete pFormatCtxDecode; 527 delete outbuf; 528 delete audiosample; 529 return; 530 } 531 -
libs/libmythtv/dtvrecorder.cpp
104 104 VERBOSE(VB_IMPORTANT, LOC_ERR + 105 105 "Could not allocate new packet buffer."); 106 106 } 107 else 108 { 109 RecorderBase::SetOption(name, value); 110 } 107 111 } 108 112 109 113 /** \fn DTVRecorder::FinishRecording(void) … … 116 120 { 117 121 if (_payload_buffer.size()) 118 122 { 119 ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 123 if (doTranscode) 124 { 125 transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 126 } 127 else 128 { 129 ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 130 } 120 131 _payload_buffer.clear(); 121 132 } 122 ringBuffer->WriterFlush(); 133 if (doTranscode) 134 { 135 transcoder->ringBuffer->SetEOF(); 136 } 137 else 138 { 139 ringBuffer->WriterFlush(); 140 } 123 141 } 124 142 125 143 if (curRecording) … … 193 211 // we have to write them first... 194 212 if (!_payload_buffer.empty()) 195 213 { 196 if (ringBuffer) 214 if (doTranscode) 215 { 216 transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 217 } 218 else 219 { 197 220 ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 221 } 198 222 _payload_buffer.clear(); 199 223 } 200 224 201 225 if (ringBuffer) 202 ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 226 if (doTranscode) 227 { 228 transcoder->ringBuffer->Write((unsigned char*)tspacket.data(), TSPacket::SIZE); 229 } 230 else 231 { 232 ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 233 } 203 234 } 204 235 205 236 /** \fn DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) … … 401 432 SavePositionMap(true); 402 433 if (ringBuffer) 403 434 { 404 ringBuffer->WriterFlush(); 435 if (doTranscode) 436 { 437 transcoder->ringBuffer->SetEOF(); 438 } 439 else 440 { 441 ringBuffer->WriterFlush(); 442 } 405 443 if (curRecording) 406 444 curRecording->SetFilesize(ringBuffer->GetRealFileSize()); 407 445 } … … 736 774 { 737 775 if (ringBuffer) 738 776 { 739 ringBuffer->Write( 740 &_payload_buffer[0], _payload_buffer.size()); 777 if (doTranscode) { 778 transcoder->ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 779 } 780 else { 781 ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 782 } 783 741 784 } 742 785 _payload_buffer.clear(); 743 786 } 744 787 745 788 if (ringBuffer) 746 ringBuffer->Write(bufstart, (bufptr - bufstart)); 789 if (doTranscode) 790 { 791 transcoder->ringBuffer->Write((unsigned char*)bufstart, (bufptr - bufstart)); 792 } 793 else 794 { 795 ringBuffer->Write(bufstart, (bufptr - bufstart)); 796 } 747 797 748 798 bufstart = bufptr; 749 799 } -
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 -
libs/libmythtv/RealRingBuffer.h
1 // -*- Mode: c++ -*- 2 /* 3 * Copyright (C) Rene Buehlmann 2009 4 * 5 * Copyright notice is in dvbrecorder.cpp of the MythTV project. 6 */ 7 8 #ifndef REALRINGBUFFER_H 9 #define REALRINGBUFFER_H 10 11 #include <qthread.h> 12 #include <qmutex.h> 13 #include <qwaitcondition.h> 14 15 using namespace std; 16 17 class RealRingBuffer 18 { 19 public: 20 RealRingBuffer(int size); 21 ~RealRingBuffer(); 22 int Write(unsigned char *buf, int len); 23 int Read(unsigned char *buf, int len); 24 void SetEOF(); 25 bool IsEOF(); 26 private: 27 char *rb; 28 int rbsize; 29 int rbrpos; 30 int rbwpos; 31 int bytes; 32 bool eof; 33 QMutex mutex; 34 QWaitCondition needData; 35 QWaitCondition needSpace; 36 }; 37 38 #endif 39 -
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); -
libs/libmythtv/RealRingBuffer.cpp
1 // -*- Mode: c++ -*- 2 /* 3 * Copyright (C) Rene Buehlmann 2009 4 * 5 * Copyright notice is in dvbrecorder.cpp of the MythTV project. 6 */ 7 8 #include "RealRingBuffer.h" 9 #include "mythverbose.h" 10 11 #define LOC QString("RealRingBuffer: ") 12 #define LOC_ERR QString("RealRingBuffer Error: ") 13 14 RealRingBuffer::RealRingBuffer(int size) 15 { 16 rbsize = size; 17 eof = false; 18 rbrpos = 0; 19 rbwpos = 0; 20 bytes = 0; 21 rb = new char[size]; 22 } 23 24 RealRingBuffer::~RealRingBuffer() 25 { 26 delete rb; 27 } 28 29 bool RealRingBuffer::IsEOF() 30 { 31 return eof; 32 } 33 34 void RealRingBuffer::SetEOF() 35 { 36 QMutexLocker locker(&mutex); 37 eof = true; 38 needData.wakeAll(); 39 } 40 41 int RealRingBuffer::Read(unsigned char *buf, int size) 42 { 43 int len = 0; 44 45 QMutexLocker locker(&mutex); 46 47 if (eof && bytes == 0) 48 { 49 return -1; 50 } 51 52 while (size > 0) 53 { 54 55 if (bytes == 0) 56 { 57 if (eof) 58 { 59 return len; 60 } 61 needData.wait(&mutex); 62 } 63 64 int rby = bytes > size ? size : bytes; 65 66 if (rbrpos + rby > rbsize) 67 { 68 rby = rbsize - rbrpos; 69 } 70 71 memcpy(buf, rb + rbrpos, rby); 72 size -= rby; 73 buf += rby; 74 bytes -= rby; 75 len += rby; 76 rbrpos = (rbrpos + rby) % rbsize; 77 needSpace.wakeAll(); 78 } 79 return len; 80 } 81 82 int RealRingBuffer::Write(unsigned char *buf, int size) 83 { 84 int len = 0; 85 QMutexLocker locker(&mutex); 86 87 while (size > 0) 88 { 89 90 if (rbsize - bytes == 0) 91 { 92 VERBOSE(VB_RECORD, LOC 93 + "Ringbuffer is full. Waiting for data read."); 94 needSpace.wait(&mutex); 95 } 96 97 int wb = rbsize - bytes > size ? size : rbsize - bytes; 98 99 if (rbwpos + wb > rbsize) 100 { 101 wb = rbsize - rbwpos; 102 } 103 104 memcpy(rb + rbwpos, buf, wb); 105 size -= wb; 106 buf += wb; 107 bytes += wb; 108 len += wb; 109 rbwpos = (rbwpos + wb) % rbsize; 110 needData.wakeAll(); 111 } 112 return len; 113 }