Panda3D
ffmpegAudioCursor.cxx
1 // Filename: ffmpegAudioCursor.cxx
2 // Created by: jyelon (01Aug2007)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "config_ffmpeg.h"
16 #include "ffmpegAudioCursor.h"
17 
18 #include "ffmpegAudio.h"
19 extern "C" {
20  #include "libavutil/dict.h"
21  #include "libavutil/opt.h"
22  #include "libavcodec/avcodec.h"
23  #include "libavformat/avformat.h"
24 }
25 
26 #ifdef HAVE_SWRESAMPLE
27 extern "C" {
28  #include "libswresample/swresample.h"
29 }
30 #endif
31 
32 TypeHandle FfmpegAudioCursor::_type_handle;
33 
34 #if LIBAVFORMAT_VERSION_MAJOR < 53
35  #define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
36 #endif
37 
38 #ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
39 // More recent versions of ffmpeg no longer define this.
40 #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
41 #endif
42 
43 ////////////////////////////////////////////////////////////////////
44 // Function: FfmpegAudioCursor::Constructor
45 // Access: Protected
46 // Description: xxx
47 ////////////////////////////////////////////////////////////////////
50  MovieAudioCursor(src),
51  _filename(src->_filename),
52  _packet(0),
53  _packet_data(0),
54  _format_ctx(0),
55  _audio_ctx(0),
56 #ifdef HAVE_SWRESAMPLE
57  _resample_ctx(0),
58 #endif
59  _buffer(0),
60  _buffer_alloc(0),
61  _frame(0)
62 {
63  if (!_ffvfile.open_vfs(_filename)) {
64  cleanup();
65  return;
66  }
67 
68  _format_ctx = _ffvfile.get_format_context();
69  nassertv(_format_ctx != NULL);
70 
71 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0)
72  if (avformat_find_stream_info(_format_ctx, NULL) < 0) {
73 #else
74  if (av_find_stream_info(_format_ctx) < 0) {
75 #endif
76  cleanup();
77  return;
78  }
79 
80  // Find the audio stream
81  for (int i = 0; i < (int)_format_ctx->nb_streams; i++) {
82  if (_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
83  _audio_index = i;
84  _audio_ctx = _format_ctx->streams[i]->codec;
85  _audio_timebase = av_q2d(_format_ctx->streams[i]->time_base);
86  _audio_rate = _audio_ctx->sample_rate;
87  _audio_channels = _audio_ctx->channels;
88  }
89  }
90 
91  if (_audio_ctx == 0) {
92  cleanup();
93  return;
94  }
95 
96  AVCodec *pAudioCodec = avcodec_find_decoder(_audio_ctx->codec_id);
97  if (pAudioCodec == 0) {
98  cleanup();
99  return;
100  }
101 
102 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0)
103  AVDictionary *opts = NULL;
104  av_dict_set(&opts, "request_sample_fmt", "s16", 0);
105  if (avcodec_open2(_audio_ctx, pAudioCodec, NULL) < 0) {
106 #else
107  if (avcodec_open(_audio_ctx, pAudioCodec) < 0) {
108 #endif
109  cleanup();
110  return;
111  }
112 
113 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0)
114  av_dict_free(&opts);
115 #endif
116 
117  // Set up the resample context if necessary.
118  if (_audio_ctx->sample_fmt != AV_SAMPLE_FMT_S16) {
119 #ifdef HAVE_SWRESAMPLE
120 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 25, 0)
121  ffmpeg_cat.error()
122  << "Codec does not use signed 16-bit sample format. Upgrade libavcodec to 53.25.0 or higher.\n";
123 #else
124  ffmpeg_cat.debug()
125  << "Codec does not use signed 16-bit sample format. Setting up swresample context.\n";
126 #endif
127 
128  _resample_ctx = swr_alloc();
129  av_opt_set_int(_resample_ctx, "in_channel_layout", _audio_ctx->channel_layout, 0);
130  av_opt_set_int(_resample_ctx, "out_channel_layout", _audio_ctx->channel_layout, 0);
131  av_opt_set_int(_resample_ctx, "in_sample_rate", _audio_ctx->sample_rate, 0);
132  av_opt_set_int(_resample_ctx, "out_sample_rate", _audio_ctx->sample_rate, 0);
133  av_opt_set_sample_fmt(_resample_ctx, "in_sample_fmt", _audio_ctx->sample_fmt, 0);
134  av_opt_set_sample_fmt(_resample_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
135 
136  if (swr_init(_resample_ctx) != 0) {
137  ffmpeg_cat.error()
138  << "Failed to set up resample context.\n";
139  _resample_ctx = NULL;
140  }
141 #else
142  ffmpeg_cat.error()
143  << "Codec does not use signed 16-bit sample format, but support for libswresample has not been enabled.\n";
144 #endif
145  }
146 
147  _length = (_format_ctx->duration * 1.0) / AV_TIME_BASE;
148  _can_seek = true;
149  _can_seek_fast = true;
150 
151 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
152  _frame = av_frame_alloc();
153 #else
154  _frame = avcodec_alloc_frame();
155 #endif
156 
157  _packet = new AVPacket;
158  _buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE / 2;
159  _buffer_alloc = new PN_int16[_buffer_size + 64];
160 
161  // Allocate enough space for 1024 samples per channel.
162  if ((_packet == 0)||(_buffer_alloc == 0)) {
163  cleanup();
164  return;
165  }
166  memset(_packet, 0, sizeof(AVPacket));
167 
168  // Align the buffer to a 64-byte boundary
169  // The ffmpeg codec likes this, because it uses SSE/SSE2.
170  _buffer = _buffer_alloc;
171  while (((size_t)_buffer) & 31) {
172  _buffer += 1;
173  }
174 
175  fetch_packet();
176  _initial_dts = _packet->dts;
177  _last_seek = 0;
178  _samples_read = 0;
179  _buffer_head = 0;
180  _buffer_tail = 0;
181 }
182 
183 ////////////////////////////////////////////////////////////////////
184 // Function: FfmpegAudioCursor::Destructor
185 // Access: Protected, Virtual
186 // Description: xxx
187 ////////////////////////////////////////////////////////////////////
190  cleanup();
191 }
192 
193 ////////////////////////////////////////////////////////////////////
194 // Function: FfmpegAudioCursor::cleanup
195 // Access: Public
196 // Description: Reset to a standard inactive state.
197 ////////////////////////////////////////////////////////////////////
198 void FfmpegAudioCursor::
199 cleanup() {
200  if (_frame) {
201 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 45, 101)
202  av_frame_free(&_frame);
203 #elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
204  avcodec_free_frame(&_frame);
205 #else
206  av_free(&_frame);
207 #endif
208  _frame = NULL;
209  }
210 
211  if (_packet) {
212  if (_packet->data) {
213 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
214  av_packet_unref(_packet);
215 #else
216  av_free_packet(_packet);
217 #endif
218  }
219  delete _packet;
220  _packet = NULL;
221  }
222 
223  if (_buffer_alloc) {
224  delete[] _buffer_alloc;
225  _buffer_alloc = 0;
226  _buffer = NULL;
227  }
228 
229  if ((_audio_ctx)&&(_audio_ctx->codec)) {
230  avcodec_close(_audio_ctx);
231  }
232  _audio_ctx = NULL;
233 
234  if (_format_ctx) {
235  _ffvfile.close();
236  _format_ctx = NULL;
237  }
238 
239 #ifdef HAVE_SWRESAMPLE
240  if (_resample_ctx) {
241  swr_free(&_resample_ctx);
242  _resample_ctx = NULL;
243  }
244 #endif
245 
246  _audio_index = -1;
247 }
248 
249 ////////////////////////////////////////////////////////////////////
250 // Function: FfmpegAudioCursor::fetch_packet
251 // Access: Protected
252 // Description: Fetches an audio packet and stores it in the
253 // packet buffer. Also sets packet_size and packet_data.
254 ////////////////////////////////////////////////////////////////////
255 void FfmpegAudioCursor::
256 fetch_packet() {
257  if (_packet->data) {
258 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
259  av_packet_unref(_packet);
260 #else
261  av_free_packet(_packet);
262 #endif
263  }
264  while (av_read_frame(_format_ctx, _packet) >= 0) {
265  if (_packet->stream_index == _audio_index) {
266  _packet_size = _packet->size;
267  _packet_data = _packet->data;
268  return;
269  }
270 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
271  av_packet_unref(_packet);
272 #else
273  av_free_packet(_packet);
274 #endif
275  }
276  _packet->data = 0;
277  _packet_size = 0;
278  _packet_data = 0;
279 }
280 
281 ////////////////////////////////////////////////////////////////////
282 // Function: FfmpegAudioCursor::reload_buffer
283 // Access: Protected
284 // Description: Reloads the audio buffer by decoding audio packets
285 // until one of those audio packets finally yields
286 // some samples. If we encounter the end of the
287 // stream, we synthesize silence.
288 ////////////////////////////////////////////////////////////////////
289 bool FfmpegAudioCursor::
290 reload_buffer() {
291 
292  while (_buffer_head == _buffer_tail) {
293  // If we're out of packets, generate silence.
294  if (_packet->data == 0) {
295  _buffer_head = 0;
296  _buffer_tail = _buffer_size;
297  memset(_buffer, 0, _buffer_size * 2);
298  return true;
299  } else if (_packet_size > 0) {
300  int bufsize = _buffer_size * 2;
301 #if LIBAVCODEC_VERSION_INT < 3349504
302  int len = avcodec_decode_audio(_audio_ctx, _buffer, &bufsize,
303  _packet_data, _packet_size);
304  movies_debug("avcodec_decode_audio returned " << len);
305 #elif LIBAVCODEC_VERSION_INT < 3414272
306  int len = avcodec_decode_audio2(_audio_ctx, _buffer, &bufsize,
307  _packet_data, _packet_size);
308  movies_debug("avcodec_decode_audio2 returned " << len);
309 #elif LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 25, 0)
310  // We should technically also consider resampling in this case,
311  // but whatever. Just upgrade your ffmpeg version if you get garbage.
312  AVPacket pkt;
313  av_init_packet(&pkt);
314  pkt.data = _packet_data;
315  pkt.size = _packet_size;
316  int len = avcodec_decode_audio3(_audio_ctx, _buffer, &bufsize, &pkt);
317  movies_debug("avcodec_decode_audio3 returned " << len);
318  av_free_packet(&pkt);
319 #else
320  int got_frame;
321  AVPacket pkt;
322  av_init_packet(&pkt);
323  pkt.data = _packet_data;
324  pkt.size = _packet_size;
325  int len = avcodec_decode_audio4(_audio_ctx, _frame, &got_frame, &pkt);
326  movies_debug("avcodec_decode_audio4 returned " << len);
327 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
328  av_packet_unref(&pkt);
329 #else
330  av_free_packet(&pkt);
331 #endif
332 
333  bufsize = 0;
334  if (got_frame) {
335 #ifdef HAVE_SWRESAMPLE
336  if (_resample_ctx) {
337  // Resample the data to signed 16-bit sample format.
338  bufsize = swr_convert(_resample_ctx, (uint8_t **)&_buffer, _buffer_size / 2, (const uint8_t**)_frame->extended_data, _frame->nb_samples);
339  bufsize *= _audio_channels * 2;
340  } else
341 #endif
342  {
343  bufsize = _frame->linesize[0];
344  memcpy(_buffer, _frame->data[0], bufsize);
345  }
346  }
347 #if LIBAVUTIL_VERSION_INT > AV_VERSION_INT(52, 19, 100)
348  av_frame_unref(_frame);
349 #endif
350 #endif
351 
352  if (len < 0) {
353  return false;
354  } else if (len == 0){
355  return true;
356  }
357  _packet_data += len;
358  _packet_size -= len;
359  if (bufsize > 0) {
360  _buffer_head = 0;
361  _buffer_tail = (bufsize/2);
362  return true;
363  }
364  } else {
365  fetch_packet();
366  }
367  }
368  return true;
369 }
370 
371 ////////////////////////////////////////////////////////////////////
372 // Function: FfmpegAudioCursor::seek
373 // Access: Protected
374 // Description: Seeks to a target location. Afterward, the
375 // packet_time is guaranteed to be less than or
376 // equal to the specified time.
377 ////////////////////////////////////////////////////////////////////
379 seek(double t) {
380  PN_int64 target_ts = (PN_int64)(t / _audio_timebase);
381  if (target_ts < (PN_int64)(_initial_dts)) {
382  // Attempts to seek before the first packet will fail.
383  target_ts = _initial_dts;
384  }
385  if (av_seek_frame(_format_ctx, _audio_index, target_ts, AVSEEK_FLAG_BACKWARD) < 0) {
386  ffmpeg_cat.error() << "Seek failure. Shutting down movie.\n";
387  cleanup();
388  return;
389  }
390  avcodec_close(_audio_ctx);
391  AVCodec *pAudioCodec = avcodec_find_decoder(_audio_ctx->codec_id);
392  if(pAudioCodec == 0) {
393  cleanup();
394  return;
395  }
396 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0)
397  if (avcodec_open2(_audio_ctx, pAudioCodec, NULL) < 0) {
398 #else
399  if (avcodec_open(_audio_ctx, pAudioCodec) < 0) {
400 #endif
401  cleanup();
402  return;
403  }
404  _buffer_head = 0;
405  _buffer_tail = 0;
406  fetch_packet();
407  double ts = _packet->dts * _audio_timebase;
408  if (t > ts) {
409  int skip = (int)((t-ts) * _audio_rate);
410  read_samples(skip, 0);
411  }
412  _last_seek = t;
413  _samples_read = 0;
414 }
415 
416 ////////////////////////////////////////////////////////////////////
417 // Function: FfmpegAudioCursor::read_samples
418 // Access: Public, Virtual
419 // Description: Read audio samples from the stream. N is the
420 // number of samples you wish to read. Your buffer
421 // must be equal in size to N * channels.
422 // Multiple-channel audio will be interleaved.
423 ////////////////////////////////////////////////////////////////////
425 read_samples(int n, PN_int16 *data) {
426  int desired = n * _audio_channels;
427 
428  while (desired > 0) {
429  if (_buffer_head == _buffer_tail) {
430  if(!reload_buffer()){
431  break;
432  }
433  movies_debug("read_samples() desired samples: " << desired << " N:" << n);
434  }
435  int available = _buffer_tail - _buffer_head;
436  int ncopy = (desired > available) ? available : desired;
437  if (ncopy) {
438  if (data != 0) {
439  memcpy(data, _buffer + _buffer_head, ncopy * 2);
440  data += ncopy;
441  }
442  desired -= ncopy;
443  _buffer_head += ncopy;
444  }
445 
446  }
447  _samples_read += n;
448 }
virtual void seek(double offset)
Seeks to a target location.
bool open_vfs(const Filename &filename)
Opens the movie file via Panda&#39;s VFS.
A stream that generates a sequence of audio samples.
Definition: ffmpegAudio.h:27
void close()
Explicitly closes the opened file.
virtual void read_samples(int n, PN_int16 *data)
Read audio samples from the stream.
virtual ~FfmpegAudioCursor()
xxx
A MovieAudio is actually any source that provides a sequence of audio samples.
FfmpegAudioCursor(FfmpegAudio *src)
xxx
AVFormatContext * get_format_context() const
Returns a pointer to the opened ffmpeg context, or NULL if the file was not successfully opened...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85