Advertisement
Guest User

ad_ffmpeg.c

a guest
Aug 5th, 2013
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.58 KB | None | 0 0
  1. /**
  2. Copyright (C) 2011-2013 Robin Gareus <robin@gareus.org>
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser Public License as published by
  6. the Free Software Foundation; either version 2.1, or (at your option)
  7. any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser Public License for more details.
  13.  
  14. You should have received a copy of the GNU Lesser General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17.  
  18. */
  19.  
  20. //#include "config.h"
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <math.h>
  26.  
  27. #include "audio_decoder/ad_plugin.h"
  28.  
  29. #ifdef HAVE_FFMPEG
  30. #include <libavcodec/avcodec.h>
  31. #include "ffcompat.h"
  32.  
  33. #ifndef MIN
  34. #define MIN(a,b) ( ( (a) < (b) )? (a) : (b) )
  35. #endif
  36. #ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
  37. #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
  38. #endif
  39.  
  40. typedef struct {
  41. AVFormatContext* formatContext;
  42. AVCodecContext* codecContext;
  43. AVCodec* codec;
  44. AVPacket packet;
  45. int audioStream;
  46. int pkt_len;
  47. uint8_t* pkt_ptr;
  48.  
  49. int16_t m_tmpBuffer[AVCODEC_MAX_AUDIO_FRAME_SIZE];
  50. int16_t* m_tmpBufferStart;
  51. unsigned long m_tmpBufferLen;
  52.  
  53. int64_t decoder_clock;
  54. int64_t output_clock;
  55. int64_t seek_frame;
  56. unsigned int samplerate;
  57. unsigned int channels;
  58. int64_t length;
  59. } ffmpeg_audio_decoder;
  60.  
  61.  
  62. static int ad_info_ffmpeg(void *sf, struct adinfo *nfo) {
  63. ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
  64. if (!priv) return -1;
  65. if (nfo) {
  66. nfo->sample_rate = priv->samplerate;
  67. nfo->channels = priv->channels;
  68. nfo->frames = priv->length;
  69. if (nfo->sample_rate==0) return -1;
  70. nfo->length = (nfo->frames * 1000) / nfo->sample_rate;
  71. nfo->bit_rate = priv->formatContext->bit_rate;
  72. nfo->bit_depth = 0;
  73. nfo->meta_data = NULL;
  74.  
  75. #ifdef WITH_GTK // XXX replace g_* functions with POSIX equiv
  76. AVDictionaryEntry *tag = NULL;
  77. // Tags in container
  78. while ((tag = av_dict_get(priv->formatContext->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
  79. dbg(2, "FTAG: %s=%s", tag->key, tag->value);
  80. char * tmp = g_strdup_printf("%s%s<i>%s</i>:%s", nfo->meta_data?nfo->meta_data:"",nfo->meta_data?"\n":"", tag->key, tag->value);
  81. if (nfo->meta_data) g_free(nfo->meta_data);
  82. nfo->meta_data = tmp;
  83. }
  84. // Tags in stream
  85. tag=NULL;
  86. AVStream *stream = priv->formatContext->streams[priv->audioStream];
  87. while ((tag = av_dict_get(stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
  88. dbg(2, "STAG: %s=%s", tag->key, tag->value);
  89. char * tmp = g_strdup_printf("%s%s<i>%s</i>:%s", nfo->meta_data?nfo->meta_data:"",nfo->meta_data?"\n":"", tag->key, tag->value);
  90. if (nfo->meta_data) g_free(nfo->meta_data);
  91. nfo->meta_data = tmp;
  92. }
  93. #endif
  94. }
  95. return 0;
  96. }
  97.  
  98. static void *ad_open_ffmpeg(const char *fn, struct adinfo *nfo) {
  99. ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) calloc(1, sizeof(ffmpeg_audio_decoder));
  100.  
  101. priv->m_tmpBufferStart=NULL;
  102. priv->m_tmpBufferLen=0;
  103. priv->decoder_clock=priv->output_clock=priv->seek_frame=0;
  104. priv->packet.size=0; priv->packet.data=NULL;
  105.  
  106. if (avformat_open_input(&priv->formatContext, fn, NULL, NULL) <0) {
  107. dbg(0, "ffmpeg is unable to open file '%s'.", fn);
  108. free(priv); return(NULL);
  109. }
  110.  
  111. if (avformat_find_stream_info(priv->formatContext, NULL) < 0) {
  112. avformat_close_input(&priv->formatContext);
  113. dbg(0, "av_find_stream_info failed" );
  114. free(priv); return(NULL);
  115. }
  116.  
  117. priv->audioStream = -1;
  118. unsigned int i;
  119. for (i=0; i<priv->formatContext->nb_streams; i++) {
  120. if (priv->formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
  121. priv->audioStream = i;
  122. break;
  123. }
  124. }
  125. if (priv->audioStream == -1) {
  126. dbg(0, "No Audio Stream found in file");
  127. avformat_close_input(&priv->formatContext);
  128. free(priv); return(NULL);
  129. }
  130.  
  131. priv->codecContext = priv->formatContext->streams[priv->audioStream]->codec;
  132. priv->codec = avcodec_find_decoder(priv->codecContext->codec_id);
  133.  
  134. if (priv->codec == NULL) {
  135. avformat_close_input(&priv->formatContext);
  136. dbg(0, "Codec not supported by ffmpeg");
  137. free(priv); return(NULL);
  138. }
  139. if (avcodec_open2(priv->codecContext, priv->codec, NULL) < 0) {
  140. dbg(0, "avcodec_open failed" );
  141. free(priv); return(NULL);
  142. }
  143.  
  144. dbg(2, "ffmpeg - audio tics: %i/%i [sec]",priv->formatContext->streams[priv->audioStream]->time_base.num,priv->formatContext->streams[priv->audioStream]->time_base.den);
  145.  
  146. int64_t len = priv->formatContext->duration - priv->formatContext->start_time;
  147.  
  148. priv->formatContext->flags|=AVFMT_FLAG_GENPTS;
  149. priv->formatContext->flags|=AVFMT_FLAG_IGNIDX;
  150.  
  151. priv->samplerate = priv->codecContext->sample_rate;
  152. priv->channels = priv->codecContext->channels ;
  153. priv->length = (int64_t)( len * priv->samplerate / AV_TIME_BASE );
  154.  
  155. if (ad_info_ffmpeg((void*)priv, nfo)) {
  156. dbg(0, "invalid file info (sample-rate==0)");
  157. free(priv); return(NULL);
  158. }
  159.  
  160. dbg(1, "ffmpeg - %s", fn);
  161. if (nfo)
  162. dbg(1, "ffmpeg - sr:%i c:%i d:%"PRIi64" f:%"PRIi64, nfo->sample_rate, nfo->channels, nfo->length, nfo->frames);
  163.  
  164. return (void*) priv;
  165. }
  166.  
  167. static int ad_close_ffmpeg(void *sf) {
  168. ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
  169. if (!priv) return -1;
  170. avcodec_close(priv->codecContext);
  171. avformat_close_input(&priv->formatContext);
  172. free(priv);
  173. return 0;
  174. }
  175.  
  176. static void int16_to_float(int16_t *in, float *out, int num_channels, int num_samples, int out_offset) {
  177. int i,ii;
  178. for (i=0;i<num_samples;i++) {
  179. for (ii=0;ii<num_channels;ii++) {
  180. out[(i+out_offset)*num_channels+ii]= (float) in[i*num_channels+ii]/ 32768.0;
  181. }
  182. }
  183. }
  184.  
  185. static ssize_t ad_read_ffmpeg(void *sf, float* d, size_t len) {
  186. ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
  187. if (!priv) return -1;
  188. size_t frames = len / priv->channels;
  189.  
  190. size_t written = 0;
  191. ssize_t ret = 0;
  192. while (ret >= 0 && written < frames) {
  193. dbg(3,"loop: %i/%i (bl:%lu)",written, frames, priv->m_tmpBufferLen );
  194. if (priv->seek_frame == 0 && priv->m_tmpBufferLen > 0 ) {
  195. int s = MIN(priv->m_tmpBufferLen / priv->channels, frames - written );
  196. int16_to_float(priv->m_tmpBufferStart, d, priv->channels, s , written);
  197. written += s;
  198. priv->output_clock+=s;
  199. s = s * priv->channels;
  200. priv->m_tmpBufferStart += s;
  201. priv->m_tmpBufferLen -= s;
  202. ret = 0;
  203. } else {
  204. priv->m_tmpBufferStart = priv->m_tmpBuffer;
  205. priv->m_tmpBufferLen = 0;
  206.  
  207. if (!priv->pkt_ptr || priv->pkt_len <1 ) {
  208. if (priv->packet.data) av_free_packet(&priv->packet);
  209. ret = av_read_frame(priv->formatContext, &priv->packet);
  210. if (ret<0) { dbg(1, "reached end of file."); break; }
  211. priv->pkt_len = priv->packet.size;
  212. priv->pkt_ptr = priv->packet.data;
  213. }
  214.  
  215. if (priv->packet.stream_index != priv->audioStream) {
  216. priv->pkt_ptr = NULL;
  217. continue;
  218. }
  219.  
  220. /* decode all chunks in packet */
  221. int data_size= AVCODEC_MAX_AUDIO_FRAME_SIZE;
  222.  
  223. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 0, 0)
  224. /* This works but is not optimal (channels may not be planar/interleaved) */
  225. AVFrame avf; // TODO statically allocate as poart of priv->..
  226. memset(&avf, 0, sizeof(AVFrame)); // not sure if that is needed
  227. int got_frame = 0;
  228. ret = avcodec_decode_audio4(priv->codecContext, &avf, &got_frame, &priv->packet);
  229. data_size = avf.linesize[0];
  230. memcpy(priv->m_tmpBuffer, avf.data[0], avf.linesize[0] * sizeof(uint8_t));
  231. #elif LIBAVUTIL_VERSION_INT > AV_VERSION_INT(49, 15, 0) && LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 20, 1) // ??
  232. // this was deprecated in LIBAVCODEC_VERSION_MAJOR 53
  233. ret = avcodec_decode_audio3(priv->codecContext,
  234. priv->m_tmpBuffer, &data_size, &priv->packet);
  235. #else
  236. int len = priv->packet.size;
  237. uint8_t *ptr = priv->packet.data;
  238. ret = avcodec_decode_audio2(priv->codecContext,
  239. priv->m_tmpBuffer, &data_size, ptr, len);
  240. #endif
  241.  
  242. if (ret < 0 || ret > priv->pkt_len) {
  243. #if 0
  244. dbg(0, "audio decode error");
  245. return -1;
  246. #endif
  247. priv->pkt_len=0;
  248. ret=0;
  249. continue;
  250. }
  251.  
  252. priv->pkt_len -= ret; priv->pkt_ptr += ret;
  253.  
  254. /* sample exact alignment */
  255. if (priv->packet.pts != AV_NOPTS_VALUE) {
  256. priv->decoder_clock = priv->samplerate * av_q2d(priv->formatContext->streams[priv->audioStream]->time_base) * priv->packet.pts;
  257. } else {
  258. dbg(0, "!!! NO PTS timestamp in file");
  259. priv->decoder_clock += (data_size>>1) / priv->channels;
  260. }
  261.  
  262. if (data_size>0) {
  263. priv->m_tmpBufferLen+= (data_size>>1); // 2 bytes per sample
  264. }
  265.  
  266. /* align buffer after seek. */
  267. if (priv->seek_frame > 0) {
  268. const int diff = priv->output_clock-priv->decoder_clock;
  269. if (diff<0) {
  270. /* seek ended up past the wanted sample */
  271. dbg(0, " !!! Audio seek failed.");
  272. return -1;
  273. } else if (priv->m_tmpBufferLen < (diff*priv->channels)) {
  274. /* wanted sample not in current buffer - keep going */
  275. dbg(2, " !!! seeked sample was not in decoded buffer. frames-to-go: %li", diff);
  276. priv->m_tmpBufferLen = 0;
  277. } else if (diff!=0 && data_size > 0) {
  278. /* wanted sample is in current buffer but not at the beginnning */
  279. dbg(2, " !!! sync buffer to seek. (diff:%i)", diff);
  280. priv->m_tmpBufferStart+= diff*priv->codecContext->channels;
  281. priv->m_tmpBufferLen -= diff*priv->codecContext->channels;
  282. #if 1
  283. memmove(priv->m_tmpBuffer, priv->m_tmpBufferStart, priv->m_tmpBufferLen);
  284. priv->m_tmpBufferStart = priv->m_tmpBuffer;
  285. #endif
  286. priv->seek_frame=0;
  287. priv->decoder_clock += diff;
  288. } else if (data_size > 0) {
  289. dbg(2, "Audio exact sync-seek (%"PRIi64" == %"PRIi64")", priv->decoder_clock, priv->seek_frame);
  290. priv->seek_frame=0;
  291. } else {
  292. dbg(0, "Error: no audio data in packet");
  293. }
  294. }
  295. //dbg(0, "PTS: decoder:%"PRIi64". - want: %"PRIi64, priv->decoder_clock, priv->output_clock);
  296. //dbg(0, "CLK: frame: %"PRIi64" T:%.3fs",priv->decoder_clock, (float) priv->decoder_clock/priv->samplerate);
  297. }
  298. }
  299. if (written!=frames) {
  300. dbg(2, "short-read");
  301. }
  302. return written * priv->channels;
  303. }
  304.  
  305. static int64_t ad_seek_ffmpeg(void *sf, int64_t pos) {
  306. ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
  307. if (!sf) return -1;
  308. if (pos == priv->output_clock) return pos;
  309.  
  310. /* flush internal buffer */
  311. priv->m_tmpBufferLen = 0;
  312. priv->seek_frame = pos;
  313. priv->output_clock = pos;
  314. priv->pkt_len = 0; priv->pkt_ptr = NULL;
  315. priv->decoder_clock = 0;
  316.  
  317. #if 0
  318. /* TODO seek at least 1 packet before target.
  319. * for mpeg compressed files, the
  320. * output may depend on past frames! */
  321. if (pos > 8192) pos -= 8192;
  322. else pos = 0;
  323. #endif
  324.  
  325. const int64_t timestamp = pos / av_q2d(priv->formatContext->streams[priv->audioStream]->time_base) / priv->samplerate;
  326. dbg(2, "seek frame:%"PRIi64" - idx:%"PRIi64, pos, timestamp);
  327.  
  328. av_seek_frame(priv->formatContext, priv->audioStream, timestamp, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
  329. avcodec_flush_buffers(priv->codecContext);
  330. return pos;
  331. }
  332.  
  333. static int ad_eval_ffmpeg(const char *f) {
  334. char *ext = strrchr(f, '.');
  335. if (!ext) return 10;
  336. // libavformat.. guess_format..
  337. return 40;
  338. }
  339. #endif
  340.  
  341. static const ad_plugin ad_ffmpeg = {
  342. #ifdef HAVE_FFMPEG
  343. &ad_eval_ffmpeg,
  344. &ad_open_ffmpeg,
  345. &ad_close_ffmpeg,
  346. &ad_info_ffmpeg,
  347. &ad_seek_ffmpeg,
  348. &ad_read_ffmpeg
  349. #else
  350. &ad_eval_null,
  351. &ad_open_null,
  352. &ad_close_null,
  353. &ad_info_null,
  354. &ad_seek_null,
  355. &ad_read_null
  356. #endif
  357. };
  358.  
  359. /* dlopen handler */
  360. const ad_plugin * adp_get_ffmpeg() {
  361. #ifdef HAVE_FFMPEG
  362. static int ffinit = 0;
  363. if (!ffinit) {
  364. ffinit=1;
  365. #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 5, 0)
  366. avcodec_init();
  367. #endif
  368. av_register_all();
  369. avcodec_register_all();
  370. if(ad_debug_level <= 1)
  371. av_log_set_level(AV_LOG_QUIET);
  372. else
  373. av_log_set_level(AV_LOG_VERBOSE);
  374. }
  375. #endif
  376. return &ad_ffmpeg;
  377. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement