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

◆ AudioOutFile()

inet::AudioOutFile::AudioOutFile ( )
inline
29 : opened(false), audio_st(nullptr), oc(nullptr) {};

◆ ~AudioOutFile()

inet::AudioOutFile::~AudioOutFile ( )
168 {
169  close();
170 }

Member Function Documentation

◆ addAudioStream()

void inet::AudioOutFile::addAudioStream ( enum AVCodecID  codec_id,
int  sampleRate,
short int  sampleBits 
)
protected
25 {
26  AVStream *st = avformat_new_stream(oc, nullptr);
27 
28  if (!st)
29  throw cRuntimeError("Could not alloc stream\n");
30 
31  AVCodecContext *c = st->codec;
32  c->codec_id = codec_id;
33  c->codec_type = AVMEDIA_TYPE_AUDIO;
34 
35  /* put sample parameters */
36  c->bit_rate = sampleRate * sampleBits;
37  c->sample_rate = sampleRate;
38  c->sample_fmt = AV_SAMPLE_FMT_S16; // FIXME hack!
39  c->channels = 1;
40  audio_st = st;
41 }

Referenced by open().

◆ close()

bool inet::AudioOutFile::close ( )
140 {
141  if (!opened)
142  return false;
143 
144  opened = false;
145 
146  /* write the trailer, if any. the trailer must be written
147  * before you close the CodecContexts open when you wrote the
148  * header; otherwise write_trailer may try to use memory that
149  * was freed on av_codec_close() */
150  av_write_trailer(oc);
151 
152  /* close each codec */
153  if (audio_st)
154  avcodec_close(audio_st->codec);
155 
156  if (!(oc->oformat->flags & AVFMT_NOFILE)) {
157  /* close the output file */
158  avio_close(oc->pb);
159  }
160 
161  /* free the stream */
162  avformat_free_context(oc);
163  oc = nullptr;
164  return true;
165 }

Referenced by inet::VoipStreamReceiver::closeConnection(), inet::VoipStreamSender::finish(), and ~AudioOutFile().

◆ isOpen()

bool inet::AudioOutFile::isOpen ( ) const
inline
35 { return opened; }

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

◆ open()

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

Referenced by inet::VoipStreamReceiver::Connection::openAudio(), and inet::VoipStreamSender::openSoundFile().

◆ write()

void inet::AudioOutFile::write ( void *  inbuf,
int  inbytes 
)
102 {
103  ASSERT(opened);
104 
105  AVCodecContext *c = audio_st->codec;
106  short int bytesPerInSample = av_get_bytes_per_sample(c->sample_fmt);
107  int samples = pktBytes / bytesPerInSample;
108 
109  AVPacket pkt;
110  av_init_packet(&pkt);
111  pkt.data = nullptr;
112  pkt.size = 0;
113  AVFrame *frame = av_frame_alloc();
114 
115  frame->nb_samples = samples;
116 
117  frame->channel_layout = AV_CH_LAYOUT_MONO;
118  frame->sample_rate = c->sample_rate;
119 
120  int ret = avcodec_fill_audio_frame(frame, /*channels*/ 1, c->sample_fmt, (const uint8_t *)(decBuf), pktBytes, 1);
121  if (ret < 0)
122  throw cRuntimeError("Error in avcodec_fill_audio_frame(): err=%d", ret);
123 
124  // The bitsPerOutSample is not 0 when codec is PCM.
125  int gotPacket;
126  ret = avcodec_encode_audio2(c, &pkt, frame, &gotPacket);
127  if (ret < 0 || gotPacket != 1)
128  throw cRuntimeError("avcodec_encode_audio() error: %d gotPacket: %d", ret, gotPacket);
129 
130  pkt.dts = 0; // HACK for libav 11
131 
132  // write the compressed frame into the media file
133  ret = av_interleaved_write_frame(oc, &pkt);
134  if (ret != 0)
135  throw cRuntimeError("Error while writing audio frame: %d", ret);
136  av_frame_free(&frame);
137 }

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

Member Data Documentation

◆ audio_st

AVStream* inet::AudioOutFile::audio_st
protected

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

◆ oc

AVFormatContext* inet::AudioOutFile::oc
protected

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

◆ opened

bool inet::AudioOutFile::opened
protected

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


The documentation for this class was generated from the following files:
inet::units::constants::c
const value< double, compose< units::m, pow< units::s, -1 > > > c(299792458)
inet::AudioOutFile::addAudioStream
void addAudioStream(enum AVCodecID codec_id, int sampleRate, short int sampleBits)
Definition: AudioOutFile.cc:24
inet::AudioOutFile::oc
AVFormatContext * oc
Definition: AudioOutFile.h:43
inet::AudioOutFile::opened
bool opened
Definition: AudioOutFile.h:41
inet::AudioOutFile::audio_st
AVStream * audio_st
Definition: AudioOutFile.h:42
inet::AudioOutFile::close
bool close()
Definition: AudioOutFile.cc:139