|
MythTV
0.26-pre
|
00001 /* -*- Mode: c++ -*- 00002 * 00003 * Class AVFormatWriter 00004 * 00005 * Copyright (C) Chris Pinkham 2011 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 */ 00021 00022 #include "mythlogging.h" 00023 #include "mythcorecontext.h" 00024 #include "NuppelVideoRecorder.h" 00025 #include "avformatwriter.h" 00026 00027 extern "C" { 00028 #if HAVE_BIGENDIAN 00029 #include "byteswap.h" 00030 #endif 00031 #include "libavutil/opt.h" 00032 } 00033 00034 #define LOC QString("AVFW(%1): ").arg(m_filename) 00035 #define LOC_ERR QString("AVFW(%1) Error: ").arg(m_filename) 00036 #define LOC_WARN QString("AVFW(%1) Warning: ").arg(m_filename) 00037 00038 AVFormatWriter::AVFormatWriter() 00039 : FileWriterBase(), 00040 00041 m_avfRingBuffer(NULL), m_ringBuffer(NULL), 00042 00043 m_ctx(NULL), 00044 m_videoStream(NULL), m_avVideoCodec(NULL), 00045 m_audioStream(NULL), m_avAudioCodec(NULL), 00046 m_picture(NULL), m_tmpPicture(NULL), 00047 m_videoOutBuf(NULL), m_videoOutBufSize(0), 00048 m_audioSamples(NULL), m_audioOutBuf(NULL), 00049 m_audioOutBufSize(0), m_audioInputFrameSize(0) 00050 { 00051 av_register_all(); 00052 avcodec_register_all(); 00053 00054 // bool debug = VERBOSE_LEVEL_CHECK(VB_LIBAV, LOG_ANY); 00055 // av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR); 00056 // av_log_set_callback(myth_av_log); 00057 } 00058 00059 AVFormatWriter::~AVFormatWriter() 00060 { 00061 QMutexLocker locker(avcodeclock); 00062 00063 if (m_pkt) 00064 { 00065 av_free_packet(m_pkt); 00066 delete m_pkt; 00067 m_pkt = NULL; 00068 } 00069 00070 if (m_audPkt) 00071 { 00072 av_free_packet(m_audPkt); 00073 delete m_audPkt; 00074 m_audPkt = NULL; 00075 } 00076 00077 if (m_ctx) 00078 { 00079 av_write_trailer(m_ctx); 00080 avio_close(m_ctx->pb); 00081 for(unsigned int i = 0; i < m_ctx->nb_streams; i++) { 00082 av_freep(&m_ctx->streams[i]); 00083 } 00084 00085 av_free(m_ctx); 00086 m_ctx = NULL; 00087 } 00088 00089 if (m_videoOutBuf) 00090 delete [] m_videoOutBuf; 00091 } 00092 00093 bool AVFormatWriter::Init(void) 00094 { 00095 if (m_videoOutBuf) 00096 delete [] m_videoOutBuf; 00097 00098 if (m_width && m_height) 00099 m_videoOutBuf = new unsigned char[m_width * m_height * 2 + 10]; 00100 00101 AVOutputFormat *fmt = av_guess_format(m_container.toAscii().constData(), 00102 NULL, NULL); 00103 if (!fmt) 00104 { 00105 LOG(VB_RECORD, LOG_ERR, LOC + 00106 QString("Init(): Unable to guess AVOutputFormat from container %1") 00107 .arg(m_container)); 00108 return false; 00109 } 00110 00111 m_fmt = *fmt; 00112 00113 if (m_width && m_height) 00114 { 00115 m_avVideoCodec = avcodec_find_encoder_by_name( 00116 m_videoCodec.toAscii().constData()); 00117 if (!m_avVideoCodec) 00118 { 00119 LOG(VB_RECORD, LOG_ERR, LOC + 00120 QString("Init(): Unable to find video codec %1").arg(m_videoCodec)); 00121 return false; 00122 } 00123 00124 m_fmt.video_codec = m_avVideoCodec->id; 00125 } 00126 else 00127 m_fmt.video_codec = CODEC_ID_NONE; 00128 00129 m_avAudioCodec = avcodec_find_encoder_by_name( 00130 m_audioCodec.toAscii().constData()); 00131 if (!m_avAudioCodec) 00132 { 00133 LOG(VB_RECORD, LOG_ERR, LOC + 00134 QString("Init(): Unable to find audio codec %1").arg(m_audioCodec)); 00135 return false; 00136 } 00137 00138 m_fmt.audio_codec = m_avAudioCodec->id; 00139 00140 m_ctx = avformat_alloc_context(); 00141 if (!m_ctx) 00142 { 00143 LOG(VB_RECORD, LOG_ERR, 00144 LOC + "Init(): Unable to allocate AVFormatContext"); 00145 return false; 00146 } 00147 00148 m_ctx->oformat = &m_fmt; 00149 00150 if (m_container == "mpegts") 00151 m_ctx->packet_size = 2324; 00152 00153 snprintf(m_ctx->filename, sizeof(m_ctx->filename), "%s", 00154 m_filename.toAscii().constData()); 00155 00156 if (m_fmt.video_codec != CODEC_ID_NONE) 00157 m_videoStream = AddVideoStream(); 00158 if (m_fmt.audio_codec != CODEC_ID_NONE) 00159 m_audioStream = AddAudioStream(); 00160 00161 m_pkt = new AVPacket; 00162 if (!m_pkt) 00163 { 00164 LOG(VB_RECORD, LOG_ERR, LOC + "Init(): error allocating AVPacket"); 00165 return false; 00166 } 00167 av_new_packet(m_pkt, m_ctx->packet_size); 00168 00169 m_audPkt = new AVPacket; 00170 if (!m_audPkt) 00171 { 00172 LOG(VB_RECORD, LOG_ERR, LOC + "Init(): error allocating AVPacket"); 00173 return false; 00174 } 00175 av_new_packet(m_audPkt, m_ctx->packet_size); 00176 00177 if ((m_videoStream) && (!OpenVideo())) 00178 { 00179 LOG(VB_RECORD, LOG_ERR, LOC + "Init(): OpenVideo() failed"); 00180 return false; 00181 } 00182 00183 if ((m_audioStream) && (!OpenAudio())) 00184 { 00185 LOG(VB_RECORD, LOG_ERR, LOC + "Init(): OpenAudio() failed"); 00186 return false; 00187 } 00188 00189 return true; 00190 } 00191 00192 bool AVFormatWriter::OpenFile(void) 00193 { 00194 if (!(m_fmt.flags & AVFMT_NOFILE)) 00195 { 00196 if (avio_open(&m_ctx->pb, m_filename.toAscii().constData(), 00197 AVIO_FLAG_WRITE) < 0) 00198 { 00199 LOG(VB_RECORD, LOG_ERR, LOC + "OpenFile(): avio_open() failed"); 00200 return false; 00201 } 00202 } 00203 00204 m_ringBuffer = RingBuffer::Create(m_filename, true); 00205 00206 if (!m_ringBuffer) 00207 { 00208 LOG(VB_RECORD, LOG_ERR, LOC + 00209 "OpenFile(): RingBuffer::Create() failed"); 00210 return false; 00211 } 00212 00213 m_avfRingBuffer = new AVFRingBuffer(m_ringBuffer); 00214 URLContext *uc = (URLContext *)m_ctx->pb->opaque; 00215 uc->prot = &AVF_RingBuffer_Protocol; 00216 uc->priv_data = (void *)m_avfRingBuffer; 00217 00218 avformat_write_header(m_ctx, NULL); 00219 00220 return true; 00221 } 00222 00223 bool AVFormatWriter::CloseFile(void) 00224 { 00225 if (m_ctx) 00226 { 00227 av_write_trailer(m_ctx); 00228 avio_close(m_ctx->pb); 00229 for(unsigned int i = 0; i < m_ctx->nb_streams; i++) { 00230 av_freep(&m_ctx->streams[i]); 00231 } 00232 00233 av_free(m_ctx); 00234 m_ctx = NULL; 00235 } 00236 00237 return true; 00238 } 00239 00240 bool AVFormatWriter::NextFrameIsKeyFrame(void) 00241 { 00242 if ((m_framesWritten % m_keyFrameDist) == 0) 00243 return true; 00244 00245 return false; 00246 } 00247 00248 bool AVFormatWriter::WriteVideoFrame(VideoFrame *frame) 00249 { 00250 AVCodecContext *c; 00251 00252 c = m_videoStream->codec; 00253 00254 uint8_t *planes[3]; 00255 int len = frame->size; 00256 unsigned char *buf = frame->buf; 00257 00258 planes[0] = buf; 00259 planes[1] = planes[0] + frame->width * frame->height; 00260 planes[2] = planes[1] + (frame->width * frame->height) / 00261 4; // (pictureFormat == PIX_FMT_YUV422P ? 2 : 4); 00262 00263 m_picture->data[0] = planes[0]; 00264 m_picture->data[1] = planes[1]; 00265 m_picture->data[2] = planes[2]; 00266 m_picture->linesize[0] = frame->width; 00267 m_picture->linesize[1] = frame->width / 2; 00268 m_picture->linesize[2] = frame->width / 2; 00269 m_picture->pts = m_framesWritten + 1; 00270 m_picture->type = FF_BUFFER_TYPE_SHARED; 00271 00272 if ((m_framesWritten % m_keyFrameDist) == 0) 00273 m_picture->pict_type = AV_PICTURE_TYPE_I; 00274 else 00275 m_picture->pict_type = AV_PICTURE_TYPE_NONE; 00276 00277 int got_pkt = 0; 00278 int ret = 0; 00279 00280 av_init_packet(m_pkt); 00281 m_pkt->data = (unsigned char *)m_videoOutBuf; 00282 m_pkt->size = len; 00283 00284 { 00285 QMutexLocker locker(avcodeclock); 00286 ret = avcodec_encode_video2(m_videoStream->codec, m_pkt, 00287 m_picture, &got_pkt); 00288 } 00289 00290 if (ret < 0 || !got_pkt) 00291 { 00292 #if 0 00293 LOG(VB_RECORD, LOG_ERR, QString("WriteVideoFrame(): cs: %1, mfw: %2, tc: %3, fn: %4").arg(m_pkt->size).arg(m_framesWritten).arg(frame->timecode).arg(frame->frameNumber)); 00294 #endif 00295 return false; 00296 } 00297 00298 if ((m_framesWritten % m_keyFrameDist) == 0) 00299 m_pkt->flags |= AV_PKT_FLAG_KEY; 00300 00301 long long tc = frame->timecode; 00302 if (m_startingTimecodeOffset == -1) 00303 m_startingTimecodeOffset = tc; 00304 tc -= m_startingTimecodeOffset; 00305 00306 m_pkt->pts = tc * m_videoStream->time_base.den / m_videoStream->time_base.num / 1000; 00307 m_pkt->dts = AV_NOPTS_VALUE; 00308 m_pkt->stream_index= m_videoStream->index; 00309 00310 // LOG(VB_RECORD, LOG_ERR, QString("WriteVideoFrame(): cs: %1, mfw: %2, pkt->pts: %3, tc: %4, fn: %5, pic->pts: %6").arg(m_pkt->size).arg(m_framesWritten).arg(m_pkt->pts).arg(frame->timecode).arg(frame->frameNumber).arg(m_picture->pts)); 00311 ret = av_interleaved_write_frame(m_ctx, m_pkt); 00312 if (ret != 0) 00313 LOG(VB_RECORD, LOG_ERR, LOC + "WriteVideoFrame(): " 00314 "av_interleaved_write_frame couldn't write Video"); 00315 00316 m_framesWritten++; 00317 00318 return true; 00319 } 00320 00321 #if HAVE_BIGENDIAN 00322 static void bswap_16_buf(short int *buf, int buf_cnt, int audio_channels) 00323 __attribute__ ((unused)); /* <- suppress compiler warning */ 00324 00325 static void bswap_16_buf(short int *buf, int buf_cnt, int audio_channels) 00326 { 00327 for (int i = 0; i < audio_channels * buf_cnt; i++) 00328 buf[i] = bswap_16(buf[i]); 00329 } 00330 #endif 00331 00332 bool AVFormatWriter::WriteAudioFrame(unsigned char *buf, int fnum, int timecode) 00333 { 00334 #if HAVE_BIGENDIAN 00335 int sample_cnt = m_audioFrameSize / m_audioBytesPerSample; 00336 bswap_16_buf((short int*) buf, sample_cnt, m_audioChannels); 00337 #endif 00338 00339 int got_packet = 0; 00340 int ret = 0; 00341 00342 av_init_packet(m_audPkt); 00343 m_audPkt->data = m_audioOutBuf; 00344 m_audPkt->size = m_audioOutBufSize; 00345 00346 m_audPicture->data[0] = buf; 00347 m_audPicture->linesize[0] = m_audioFrameSize; 00348 m_audPicture->nb_samples = m_audioFrameSize; 00349 m_audPicture->format = AV_SAMPLE_FMT_S16; 00350 00351 { 00352 QMutexLocker locker(avcodeclock); 00353 ret = avcodec_encode_audio2(m_audioStream->codec, m_audPkt, 00354 m_audPicture, &got_packet); 00355 } 00356 00357 if (ret < 0 || !got_packet) 00358 { 00359 #if 0 00360 LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): No Encoded Data: cs: %1, mfw: %2, tc: %3, fn: %4").arg(m_audPkt->size).arg(m_framesWritten).arg(timecode).arg(fnum)); 00361 #endif 00362 return false; 00363 } 00364 00365 long long tc = timecode; 00366 if (m_startingTimecodeOffset == -1) 00367 m_startingTimecodeOffset = tc; 00368 tc -= m_startingTimecodeOffset; 00369 00370 if (m_avVideoCodec) 00371 m_audPkt->pts = tc * m_videoStream->time_base.den / m_videoStream->time_base.num / 1000; 00372 else 00373 m_audPkt->pts = tc * m_audioStream->time_base.den / m_audioStream->time_base.num / 1000; 00374 00375 m_audPkt->dts = AV_NOPTS_VALUE; 00376 m_audPkt->flags |= AV_PKT_FLAG_KEY; 00377 m_audPkt->data = (uint8_t*)m_audioOutBuf; 00378 m_audPkt->stream_index = m_audioStream->index; 00379 00380 // LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): cs: %1, mfw: %2, pkt->pts: %3, tc: %4, fn: %5").arg(m_audPkt->size).arg(m_framesWritten).arg(m_audPkt->pts).arg(timecode).arg(fnum)); 00381 00382 ret = av_interleaved_write_frame(m_ctx, m_audPkt); 00383 if (ret != 0) 00384 LOG(VB_RECORD, LOG_ERR, LOC + "WriteAudioFrame(): " 00385 "av_interleaved_write_frame couldn't write Audio"); 00386 00387 return true; 00388 } 00389 00390 bool AVFormatWriter::WriteTextFrame(int vbimode, unsigned char *buf, int len, 00391 int timecode, int pagenr) 00392 { 00393 return true; 00394 } 00395 00396 bool AVFormatWriter::ReOpen(QString filename) 00397 { 00398 bool result = m_ringBuffer->ReOpen(filename); 00399 00400 if (result) 00401 m_filename = filename; 00402 00403 return result; 00404 } 00405 00406 AVStream* AVFormatWriter::AddVideoStream(void) 00407 { 00408 AVCodecContext *c; 00409 AVStream *st; 00410 00411 st = avformat_new_stream(m_ctx, NULL); 00412 if (!st) 00413 { 00414 LOG(VB_RECORD, LOG_ERR, 00415 LOC + "AddVideoStream(): avformat_new_stream() failed"); 00416 return NULL; 00417 } 00418 st->id = 0; 00419 00420 c = st->codec; 00421 00422 c->codec_id = m_ctx->oformat->video_codec; 00423 c->codec_type = AVMEDIA_TYPE_VIDEO; 00424 c->bit_rate = m_videoBitrate; 00425 c->width = m_width; 00426 c->height = m_height; 00427 00428 // c->sample_aspect_ratio.num = (int)floor(m_aspect * 10000); 00429 // c->sample_aspect_ratio.den = 10000; 00430 00431 c->time_base = GetCodecTimeBase(); 00432 00433 st->time_base.den = 90000; 00434 st->time_base.num = 1; 00435 st->r_frame_rate.num = 0; 00436 st->r_frame_rate.den = 0; 00437 00438 c->gop_size = m_keyFrameDist; 00439 c->pix_fmt = PIX_FMT_YUV420P; 00440 c->thread_count = m_encodingThreadCount; 00441 00442 if (c->codec_id == CODEC_ID_MPEG2VIDEO) { 00443 c->max_b_frames = 2; 00444 } 00445 else if (c->codec_id == CODEC_ID_MPEG1VIDEO) 00446 { 00447 c->mb_decision = 2; 00448 } 00449 else if (c->codec_id == CODEC_ID_H264) 00450 { 00451 av_opt_set(c->priv_data, "profile", "baseline", 0); 00452 00453 if ((c->height <= 240) && 00454 (c->width <= 320) && 00455 (c->bit_rate <= 768000)) 00456 { 00457 c->level = 13; 00458 } 00459 else if (c->width >= 960) 00460 { 00461 if (c->width >= 1024) 00462 c->level = 41; 00463 else 00464 c->level = 31; 00465 00466 av_opt_set(c->priv_data, "profile", "main", 0); 00467 } 00468 else 00469 { 00470 c->level = 30; 00471 } 00472 00473 c->coder_type = 0; 00474 c->max_b_frames = 0; 00475 c->slices = 8; 00476 00477 c->flags |= CODEC_FLAG_LOOP_FILTER; 00478 c->me_cmp |= 1; 00479 c->me_method = ME_HEX; 00480 c->me_subpel_quality = 6; 00481 c->me_range = 16; 00482 c->keyint_min = 25; 00483 c->scenechange_threshold = 40; 00484 c->i_quant_factor = 0.71; 00485 c->b_frame_strategy = 1; 00486 c->qcompress = 0.6; 00487 c->qmin = 10; 00488 c->qmax = 51; 00489 c->max_qdiff = 4; 00490 c->refs = 3; 00491 c->trellis = 0; 00492 00493 av_opt_set(c, "partitions", "i8x8,i4x4,p8x8,b8x8", 0); 00494 av_opt_set_int(c, "direct-pred", 1, 0); 00495 av_opt_set_int(c, "rc-lookahead", 0, 0); 00496 av_opt_set_int(c, "fast-pskip", 1, 0); 00497 av_opt_set_int(c, "mixed-refs", 1, 0); 00498 av_opt_set_int(c, "8x8dct", 0, 0); 00499 av_opt_set_int(c, "weightb", 0, 0); 00500 } 00501 00502 if(m_ctx->oformat->flags & AVFMT_GLOBALHEADER) 00503 c->flags |= CODEC_FLAG_GLOBAL_HEADER; 00504 00505 // LOG(VB_RECORD, LOG_ERR, LOC + QString("AddVideoStream(): br: %1, gs: %2, tb: %3/%4, w: %5, h: %6").arg(c->bit_rate).arg(c->gop_size).arg(c->time_base.den).arg(c->time_base.num).arg(c->width).arg(c->height)); 00506 00507 return st; 00508 } 00509 00510 bool AVFormatWriter::OpenVideo(void) 00511 { 00512 AVCodec *codec; 00513 AVCodecContext *c; 00514 00515 c = m_videoStream->codec; 00516 00517 codec = avcodec_find_encoder(c->codec_id); 00518 if (!codec) 00519 { 00520 LOG(VB_RECORD, LOG_ERR, 00521 LOC + "OpenVideo(): avcodec_find_encoder() failed"); 00522 return false; 00523 } 00524 00525 if (avcodec_open2(c, codec, NULL) < 0) 00526 { 00527 LOG(VB_RECORD, LOG_ERR, 00528 LOC + "OpenVideo(): avcodec_open() failed"); 00529 return false; 00530 } 00531 00532 m_videoOutBuf = NULL; 00533 if (!(m_ctx->oformat->flags & AVFMT_RAWPICTURE)) { 00534 m_videoOutBufSize = 200000; 00535 m_videoOutBuf = (unsigned char *)av_malloc(m_videoOutBufSize); 00536 } 00537 00538 m_picture = AllocPicture(c->pix_fmt); 00539 if (!m_picture) 00540 { 00541 LOG(VB_RECORD, LOG_ERR, 00542 LOC + "OpenVideo(): AllocPicture() failed"); 00543 return false; 00544 } 00545 00546 m_tmpPicture = NULL; 00547 if (c->pix_fmt != PIX_FMT_YUV420P) 00548 { 00549 m_tmpPicture = AllocPicture(PIX_FMT_YUV420P); 00550 if (!m_tmpPicture) 00551 { 00552 LOG(VB_RECORD, LOG_ERR, 00553 LOC + "OpenVideo(): m_tmpPicture AllocPicture() failed"); 00554 return false; 00555 } 00556 } 00557 00558 return true; 00559 } 00560 00561 AVStream* AVFormatWriter::AddAudioStream(void) 00562 { 00563 AVCodecContext *c; 00564 AVStream *st; 00565 00566 st = avformat_new_stream(m_ctx, NULL); 00567 if (!st) 00568 { 00569 LOG(VB_RECORD, LOG_ERR, 00570 LOC + "AddAudioStream(): avformat_new_stream() failed"); 00571 return NULL; 00572 } 00573 st->id = 1; 00574 00575 c = st->codec; 00576 c->codec_id = m_ctx->oformat->audio_codec; 00577 c->codec_type = AVMEDIA_TYPE_AUDIO; 00578 00579 c->sample_fmt = AV_SAMPLE_FMT_S16; 00580 m_audioBytesPerSample = m_audioChannels * 2; 00581 00582 c->bit_rate = m_audioBitrate; 00583 c->sample_rate = m_audioSampleRate; 00584 c->channels = m_audioChannels; 00585 00586 // c->flags |= CODEC_FLAG_QSCALE; // VBR 00587 // c->global_quality = blah; 00588 00589 if (!m_avVideoCodec) 00590 { 00591 c->time_base = GetCodecTimeBase(); 00592 st->time_base.den = 90000; 00593 st->time_base.num = 1; 00594 } 00595 00596 // LOG(VB_RECORD, LOG_ERR, LOC + QString("AddAudioStream(): br: %1, sr, %2, c: %3, tb: %4/%5").arg(c->bit_rate).arg(c->sample_rate).arg(c->channels).arg(c->time_base.den).arg(c->time_base.num)); 00597 00598 // Disable this for support on some devices 00599 //if (c->codec_id == CODEC_ID_AAC) 00600 // c->profile = FF_PROFILE_AAC_MAIN; 00601 00602 if(m_ctx->oformat->flags & AVFMT_GLOBALHEADER) 00603 c->flags |= CODEC_FLAG_GLOBAL_HEADER; 00604 00605 return st; 00606 } 00607 00608 bool AVFormatWriter::OpenAudio(void) 00609 { 00610 AVCodecContext *c; 00611 AVCodec *codec; 00612 00613 c = m_audioStream->codec; 00614 00615 c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; 00616 00617 codec = avcodec_find_encoder(c->codec_id); 00618 if (!codec) 00619 { 00620 LOG(VB_RECORD, LOG_ERR, 00621 LOC + "OpenAudio(): avcodec_find_encoder() failed"); 00622 return false; 00623 } 00624 00625 if (avcodec_open2(c, codec, NULL) < 0) 00626 { 00627 LOG(VB_RECORD, LOG_ERR, 00628 LOC + "OpenAudio(): avcodec_open() failed"); 00629 return false; 00630 } 00631 00632 m_audioFrameSize = c->frame_size; 00633 00634 m_audioOutBufSize = (int)(1.25 * 16384 * 7200); 00635 //m_audioOutBufSize = c->frame_size * 2 * c->channels; 00636 00637 m_audioOutBuf = (unsigned char *)av_malloc(m_audioOutBufSize); 00638 00639 if (c->frame_size <= 1) { 00640 m_audioInputFrameSize = m_audioOutBufSize / c->channels; 00641 switch(m_audioStream->codec->codec_id) { 00642 case CODEC_ID_PCM_S16LE: 00643 case CODEC_ID_PCM_S16BE: 00644 case CODEC_ID_PCM_U16LE: 00645 case CODEC_ID_PCM_U16BE: 00646 m_audioInputFrameSize >>= 1; 00647 break; 00648 default: 00649 break; 00650 } 00651 } else { 00652 m_audioInputFrameSize = c->frame_size; 00653 } 00654 m_audioSamples = 00655 (unsigned int *)av_malloc(m_audioInputFrameSize * 2 * c->channels); 00656 00657 m_audPicture = avcodec_alloc_frame(); 00658 if (!m_audPicture) 00659 { 00660 LOG(VB_RECORD, LOG_ERR, 00661 LOC + "OpenAudio(): alloc_frame() failed"); 00662 return false; 00663 } 00664 00665 return true; 00666 } 00667 00668 AVFrame* AVFormatWriter::AllocPicture(enum PixelFormat pix_fmt) 00669 { 00670 AVFrame *picture; 00671 unsigned char *picture_buf; 00672 int size; 00673 00674 picture = avcodec_alloc_frame(); 00675 if (!picture) 00676 { 00677 LOG(VB_RECORD, LOG_ERR, 00678 LOC + "AllocPicture(): avcodec_alloc_frame() failed"); 00679 return NULL; 00680 } 00681 size = avpicture_get_size(pix_fmt, m_width, m_height); 00682 picture_buf = (unsigned char *)av_malloc(size); 00683 if (!picture_buf) 00684 { 00685 LOG(VB_RECORD, LOG_ERR, LOC + "AllocPicture(): av_malloc() failed"); 00686 av_free(picture); 00687 return NULL; 00688 } 00689 avpicture_fill((AVPicture *)picture, picture_buf, 00690 pix_fmt, m_width, m_height); 00691 return picture; 00692 } 00693 00694 AVRational AVFormatWriter::GetCodecTimeBase(void) 00695 { 00696 AVRational result; 00697 00698 result.den = (int)floor(m_frameRate * 100); 00699 result.num = 100; 00700 00701 if (m_avVideoCodec && m_avVideoCodec->supported_framerates) { 00702 const AVRational *p= m_avVideoCodec->supported_framerates; 00703 AVRational req = 00704 (AVRational){result.den, result.num}; 00705 const AVRational *best = NULL; 00706 AVRational best_error= (AVRational){INT_MAX, 1}; 00707 for(; p->den!=0; p++) { 00708 AVRational error = av_sub_q(req, *p); 00709 if (error.num <0) 00710 error.num *= -1; 00711 if (av_cmp_q(error, best_error) < 0) { 00712 best_error = error; 00713 best = p; 00714 } 00715 } 00716 00717 if (best && best->num && best->den) 00718 { 00719 result.den = best->num; 00720 result.num = best->den; 00721 } 00722 } 00723 00724 if (result.den == 2997) 00725 { 00726 result.den = 30000; 00727 result.num = 1001; 00728 } 00729 else if (result.den == 5994) 00730 { 00731 result.den = 60000; 00732 result.num = 1001; 00733 } 00734 00735 return result; 00736 } 00737 00738 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 00739
1.7.6.1