MythTV  0.26-pre
avformatwriter.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends