Panda3D
 All Classes Functions Variables Enumerations
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  av_free_packet(_packet);
214  }
215  delete _packet;
216  _packet = NULL;
217  }
218 
219  if (_buffer_alloc) {
220  delete[] _buffer_alloc;
221  _buffer_alloc = 0;
222  _buffer = NULL;
223  }
224 
225  if ((_audio_ctx)&&(_audio_ctx->codec)) {
226  avcodec_close(_audio_ctx);
227  }
228  _audio_ctx = NULL;
229 
230  if (_format_ctx) {
231  _ffvfile.close();
232  _format_ctx = NULL;
233  }
234 
235 #ifdef HAVE_SWRESAMPLE
236  if (_resample_ctx) {
237  swr_free(&_resample_ctx);
238  _resample_ctx = NULL;
239  }
240 #endif
241 
242  _audio_index = -1;
243 }
244 
245 ////////////////////////////////////////////////////////////////////
246 // Function: FfmpegAudioCursor::fetch_packet
247 // Access: Protected
248 // Description: Fetches an audio packet and stores it in the
249 // packet buffer. Also sets packet_size and packet_data.
250 ////////////////////////////////////////////////////////////////////
251 void FfmpegAudioCursor::
252 fetch_packet() {
253  if (_packet->data) {
254  av_free_packet(_packet);
255  }
256  while (av_read_frame(_format_ctx, _packet) >= 0) {
257  if (_packet->stream_index == _audio_index) {
258  _packet_size = _packet->size;
259  _packet_data = _packet->data;
260  return;
261  }
262  av_free_packet(_packet);
263  }
264  _packet->data = 0;
265  _packet_size = 0;
266  _packet_data = 0;
267 }
268 
269 ////////////////////////////////////////////////////////////////////
270 // Function: FfmpegAudioCursor::reload_buffer
271 // Access: Protected
272 // Description: Reloads the audio buffer by decoding audio packets
273 // until one of those audio packets finally yields
274 // some samples. If we encounter the end of the
275 // stream, we synthesize silence.
276 ////////////////////////////////////////////////////////////////////
277 bool FfmpegAudioCursor::
278 reload_buffer() {
279 
280  while (_buffer_head == _buffer_tail) {
281  // If we're out of packets, generate silence.
282  if (_packet->data == 0) {
283  _buffer_head = 0;
284  _buffer_tail = _buffer_size;
285  memset(_buffer, 0, _buffer_size * 2);
286  return true;
287  } else if (_packet_size > 0) {
288  int bufsize = _buffer_size * 2;
289 #if LIBAVCODEC_VERSION_INT < 3349504
290  int len = avcodec_decode_audio(_audio_ctx, _buffer, &bufsize,
291  _packet_data, _packet_size);
292  movies_debug("avcodec_decode_audio returned " << len);
293 #elif LIBAVCODEC_VERSION_INT < 3414272
294  int len = avcodec_decode_audio2(_audio_ctx, _buffer, &bufsize,
295  _packet_data, _packet_size);
296  movies_debug("avcodec_decode_audio2 returned " << len);
297 #elif LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 25, 0)
298  // We should technically also consider resampling in this case,
299  // but whatever. Just upgrade your ffmpeg version if you get garbage.
300  AVPacket pkt;
301  av_init_packet(&pkt);
302  pkt.data = _packet_data;
303  pkt.size = _packet_size;
304  int len = avcodec_decode_audio3(_audio_ctx, _buffer, &bufsize, &pkt);
305  movies_debug("avcodec_decode_audio3 returned " << len);
306  av_free_packet(&pkt);
307 #else
308  int got_frame;
309  AVPacket pkt;
310  av_init_packet(&pkt);
311  pkt.data = _packet_data;
312  pkt.size = _packet_size;
313  int len = avcodec_decode_audio4(_audio_ctx, _frame, &got_frame, &pkt);
314  movies_debug("avcodec_decode_audio4 returned " << len);
315  av_free_packet(&pkt);
316 
317  bufsize = 0;
318  if (got_frame) {
319 #ifdef HAVE_SWRESAMPLE
320  if (_resample_ctx) {
321  // Resample the data to signed 16-bit sample format.
322  bufsize = swr_convert(_resample_ctx, (uint8_t **)&_buffer, _buffer_size / 2, (const uint8_t**)_frame->extended_data, _frame->nb_samples);
323  bufsize *= _audio_channels * 2;
324  } else
325 #endif
326  {
327  bufsize = _frame->linesize[0];
328  memcpy(_buffer, _frame->data[0], bufsize);
329  }
330  }
331 #if LIBAVUTIL_VERSION_INT > AV_VERSION_INT(52, 19, 100)
332  av_frame_unref(_frame);
333 #endif
334 #endif
335 
336  if (len < 0) {
337  return false;
338  } else if (len == 0){
339  return true;
340  }
341  _packet_data += len;
342  _packet_size -= len;
343  if (bufsize > 0) {
344  _buffer_head = 0;
345  _buffer_tail = (bufsize/2);
346  return true;
347  }
348  } else {
349  fetch_packet();
350  }
351  }
352  return true;
353 }
354 
355 ////////////////////////////////////////////////////////////////////
356 // Function: FfmpegAudioCursor::seek
357 // Access: Protected
358 // Description: Seeks to a target location. Afterward, the
359 // packet_time is guaranteed to be less than or
360 // equal to the specified time.
361 ////////////////////////////////////////////////////////////////////
363 seek(double t) {
364  PN_int64 target_ts = (PN_int64)(t / _audio_timebase);
365  if (target_ts < (PN_int64)(_initial_dts)) {
366  // Attempts to seek before the first packet will fail.
367  target_ts = _initial_dts;
368  }
369  if (av_seek_frame(_format_ctx, _audio_index, target_ts, AVSEEK_FLAG_BACKWARD) < 0) {
370  ffmpeg_cat.error() << "Seek failure. Shutting down movie.\n";
371  cleanup();
372  return;
373  }
374  avcodec_close(_audio_ctx);
375  AVCodec *pAudioCodec = avcodec_find_decoder(_audio_ctx->codec_id);
376  if(pAudioCodec == 0) {
377  cleanup();
378  return;
379  }
380 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0)
381  if (avcodec_open2(_audio_ctx, pAudioCodec, NULL) < 0) {
382 #else
383  if (avcodec_open(_audio_ctx, pAudioCodec) < 0) {
384 #endif
385  cleanup();
386  return;
387  }
388  _buffer_head = 0;
389  _buffer_tail = 0;
390  fetch_packet();
391  double ts = _packet->dts * _audio_timebase;
392  if (t > ts) {
393  int skip = (int)((t-ts) * _audio_rate);
394  read_samples(skip, 0);
395  }
396  _last_seek = t;
397  _samples_read = 0;
398 }
399 
400 ////////////////////////////////////////////////////////////////////
401 // Function: FfmpegAudioCursor::read_samples
402 // Access: Public, Virtual
403 // Description: Read audio samples from the stream. N is the
404 // number of samples you wish to read. Your buffer
405 // must be equal in size to N * channels.
406 // Multiple-channel audio will be interleaved.
407 ////////////////////////////////////////////////////////////////////
409 read_samples(int n, PN_int16 *data) {
410  int desired = n * _audio_channels;
411 
412  while (desired > 0) {
413  if (_buffer_head == _buffer_tail) {
414  if(!reload_buffer()){
415  break;
416  }
417  movies_debug("read_samples() desired samples: " << desired << " N:" << n);
418  }
419  int available = _buffer_tail - _buffer_head;
420  int ncopy = (desired > available) ? available : desired;
421  if (ncopy) {
422  if (data != 0) {
423  memcpy(data, _buffer + _buffer_head, ncopy * 2);
424  data += ncopy;
425  }
426  desired -= ncopy;
427  _buffer_head += ncopy;
428  }
429 
430  }
431  _samples_read += n;
432 }
AVFormatContext * get_format_context() const
Returns a pointer to the opened ffmpeg context, or NULL if the file was not successfully opened...
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
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85