INET Framework for OMNeT++/OMNEST
inet::AudioOutFile Class Reference

Records audio into a file. More...

#include <AudioOutFile.h>

Public Member Functions

 AudioOutFile ()
 
 ~AudioOutFile ()
 
void open (const char *resultFile, int sampleRate, short int sampleBits)
 
void write (void *inbuf, int inbytes)
 
bool close ()
 
bool isOpen () const
 

Protected Member Functions

void addAudioStream (enum AVCodecID codec_id, int sampleRate, short int sampleBits)
 

Protected Attributes

bool opened
 
AVStream * audio_st
 
AVFormatContext * oc
 

Detailed Description

Records audio into a file.

Constructor & Destructor Documentation

inet::AudioOutFile::AudioOutFile ( )
inline
40 : opened(false), audio_st(nullptr), oc(nullptr) {};
bool opened
Definition: AudioOutFile.h:52
AVStream * audio_st
Definition: AudioOutFile.h:53
AVFormatContext * oc
Definition: AudioOutFile.h:54
inet::AudioOutFile::~AudioOutFile ( )
179 {
180  close();
181 }
bool close()
Definition: AudioOutFile.cc:149

Member Function Documentation

void inet::AudioOutFile::addAudioStream ( enum AVCodecID  codec_id,
int  sampleRate,
short int  sampleBits 
)
protected

Referenced by open().

34 {
35  AVStream *st = avformat_new_stream(oc, nullptr);
36 
37  if (!st)
38  throw cRuntimeError("Could not alloc stream\n");
39 
40  AVCodecContext *c = st->codec;
41  c->codec_id = codec_id;
42  c->codec_type = AVMEDIA_TYPE_AUDIO;
43 
44  /* put sample parameters */
45  c->bit_rate = sampleRate * sampleBits;
46  c->sample_rate = sampleRate;
47  c->sample_fmt = AV_SAMPLE_FMT_S16; //FIXME hack!
48  c->channels = 1;
49  audio_st = st;
50 }
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
AVStream * audio_st
Definition: AudioOutFile.h:53
AVFormatContext * oc
Definition: AudioOutFile.h:54
bool inet::AudioOutFile::close ( )

Referenced by inet::VoIPStreamReceiver::closeConnection(), inet::VoIPStreamSender::finish(), and ~AudioOutFile().

150 {
151  if (!opened)
152  return false;
153 
154  opened = false;
155 
156  /* write the trailer, if any. the trailer must be written
157  * before you close the CodecContexts open when you wrote the
158  * header; otherwise write_trailer may try to use memory that
159  * was freed on av_codec_close() */
160  av_write_trailer(oc);
161 
162  /* close each codec */
163  if (audio_st)
164  avcodec_close(audio_st->codec);
165 
166 
167  if (!(oc->oformat->flags & AVFMT_NOFILE)) {
168  /* close the output file */
169  avio_close(oc->pb);
170  }
171 
172  /* free the stream */
173  avformat_free_context(oc);
174  oc = nullptr;
175  return true;
176 }
bool opened
Definition: AudioOutFile.h:52
AVStream * audio_st
Definition: AudioOutFile.h:53
AVFormatContext * oc
Definition: AudioOutFile.h:54
bool inet::AudioOutFile::isOpen ( ) const
inline

Referenced by inet::VoIPStreamSender::generatePacket().

46 { return opened; }
bool opened
Definition: AudioOutFile.h:52
void inet::AudioOutFile::open ( const char *  resultFile,
int  sampleRate,
short int  sampleBits 
)

Referenced by inet::VoIPStreamSender::openSoundFile().

53 {
54  ASSERT(!opened);
55 
56  opened = true;
57 
58  // auto detect the output format from the name. default is WAV
59  AVOutputFormat *fmt = av_guess_format(nullptr, resultFile, nullptr);
60  if (!fmt) {
61  EV_WARN << "Could not deduce output format from file extension: using WAV.\n";
62  fmt = av_guess_format("wav", nullptr, nullptr);
63  }
64  if (!fmt) {
65  throw cRuntimeError("Could not find suitable output format for filename '%s'", resultFile);
66  }
67 
68  // allocate the output media context
69  oc = avformat_alloc_context();
70  if (!oc)
71  throw cRuntimeError("Memory error at avformat_alloc_context()");
72 
73  oc->oformat = fmt;
74  snprintf(oc->filename, sizeof(oc->filename), "%s", resultFile);
75 
76  // add the audio stream using the default format codecs and initialize the codecs
77  audio_st = nullptr;
78  if (fmt->audio_codec != AV_CODEC_ID_NONE)
79  addAudioStream(fmt->audio_codec, sampleRate, sampleBits);
80 
81  av_dump_format(oc, 0, resultFile, 1);
82 
83  /* now that all the parameters are set, we can open the audio and
84  video codecs and allocate the necessary encode buffers */
85  if (audio_st) {
86  AVCodecContext *c = audio_st->codec;
87 
88  /* find the audio encoder */
89  AVCodec *avcodec = avcodec_find_encoder(c->codec_id);
90  if (!avcodec)
91  throw cRuntimeError("Codec %d not found", c->codec_id);
92 
93  /* open it */
94  if (avcodec_open2(c, avcodec, nullptr) < 0)
95  throw cRuntimeError("Could not open codec %d", c->codec_id);
96  }
97 
98  /* open the output file, if needed */
99  if (!(fmt->flags & AVFMT_NOFILE)) {
100  if (avio_open(&oc->pb, resultFile, AVIO_FLAG_WRITE) < 0)
101  throw cRuntimeError("Could not open '%s'", resultFile);
102  }
103 
104  // write the stream header
105  avformat_write_header(oc, nullptr);
106 }
void addAudioStream(enum AVCodecID codec_id, int sampleRate, short int sampleBits)
Definition: AudioOutFile.cc:33
bool opened
Definition: AudioOutFile.h:52
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
AVStream * audio_st
Definition: AudioOutFile.h:53
AVFormatContext * oc
Definition: AudioOutFile.h:54
void inet::AudioOutFile::write ( void *  inbuf,
int  inbytes 
)

Referenced by inet::VoIPStreamSender::generatePacket().

109 {
110  ASSERT(opened);
111 
112  AVCodecContext *c = audio_st->codec;
113  short int bytesPerInSample = av_get_bytes_per_sample(c->sample_fmt);
114  int samples = pktBytes / bytesPerInSample;
115 
116  AVPacket pkt;
117  av_init_packet(&pkt);
118  pkt.data = nullptr;
119  pkt.size = 0;
120  AVFrame *frame = av_frame_alloc();
121 
122  frame->nb_samples = samples;
123 
124 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
125  frame->channel_layout = AV_CH_LAYOUT_MONO;
126  frame->sample_rate = c->sample_rate;
127 #endif // if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
128 
129  int ret = avcodec_fill_audio_frame(frame, /*channels*/ 1, c->sample_fmt,
130  (const uint8_t *)(decBuf), pktBytes, 1);
131  if (ret < 0)
132  throw cRuntimeError("Error in avcodec_fill_audio_frame(): err=%d", ret);
133 
134  // The bitsPerOutSample is not 0 when codec is PCM.
135  int gotPacket;
136  ret = avcodec_encode_audio2(c, &pkt, frame, &gotPacket);
137  if (ret < 0 || gotPacket != 1)
138  throw cRuntimeError("avcodec_encode_audio() error: %d gotPacket: %d", ret, gotPacket);
139 
140  pkt.dts = 0; //HACK for libav 11
141 
142  // write the compressed frame into the media file
143  ret = av_interleaved_write_frame(oc, &pkt);
144  if (ret != 0)
145  throw cRuntimeError("Error while writing audio frame: %d", ret);
146  av_frame_free(&frame);
147 }
bool opened
Definition: AudioOutFile.h:52
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
AVStream * audio_st
Definition: AudioOutFile.h:53
AVFormatContext * oc
Definition: AudioOutFile.h:54

Member Data Documentation

AVStream* inet::AudioOutFile::audio_st
protected

Referenced by addAudioStream(), close(), open(), and write().

AVFormatContext* inet::AudioOutFile::oc
protected

Referenced by addAudioStream(), close(), open(), and write().

bool inet::AudioOutFile::opened
protected

Referenced by close(), open(), and write().


The documentation for this class was generated from the following files: