alffmpeg.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /*
  2. * FFmpeg Decoder Helpers
  3. *
  4. * Copyright (c) 2011 by Chris Robinson <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. /* This file contains routines for helping to decode audio using libavformat
  25. * and libavcodec (ffmpeg). There's very little OpenAL-specific code here. */
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <signal.h>
  30. #include <assert.h>
  31. #include "AL/al.h"
  32. #include "AL/alc.h"
  33. #include "AL/alext.h"
  34. #include "alhelpers.h"
  35. #include "alffmpeg.h"
  36. static size_t NextPowerOf2(size_t value)
  37. {
  38. size_t powerOf2 = 1;
  39. if(value)
  40. {
  41. value--;
  42. while(value)
  43. {
  44. value >>= 1;
  45. powerOf2 <<= 1;
  46. }
  47. }
  48. return powerOf2;
  49. }
  50. struct MemData {
  51. char *buffer;
  52. size_t length;
  53. size_t pos;
  54. };
  55. static int MemData_read(void *opaque, uint8_t *buf, int buf_size)
  56. {
  57. struct MemData *membuf = (struct MemData*)opaque;
  58. int rem = membuf->length - membuf->pos;
  59. if(rem > buf_size)
  60. rem = buf_size;
  61. memcpy(buf, &membuf->buffer[membuf->pos], rem);
  62. membuf->pos += rem;
  63. return rem;
  64. }
  65. static int MemData_write(void *opaque, uint8_t *buf, int buf_size)
  66. {
  67. struct MemData *membuf = (struct MemData*)opaque;
  68. int rem = membuf->length - membuf->pos;
  69. if(rem > buf_size)
  70. rem = buf_size;
  71. memcpy(&membuf->buffer[membuf->pos], buf, rem);
  72. membuf->pos += rem;
  73. return rem;
  74. }
  75. static int64_t MemData_seek(void *opaque, int64_t offset, int whence)
  76. {
  77. struct MemData *membuf = (struct MemData*)opaque;
  78. whence &= ~AVSEEK_FORCE;
  79. switch(whence)
  80. {
  81. case SEEK_SET:
  82. if(offset < 0 || (uint64_t)offset > membuf->length)
  83. return -1;
  84. membuf->pos = offset;
  85. break;
  86. case SEEK_CUR:
  87. if((offset >= 0 && (uint64_t)offset > membuf->length-membuf->pos) ||
  88. (offset < 0 && (uint64_t)(-offset) > membuf->pos))
  89. return -1;
  90. membuf->pos += offset;
  91. break;
  92. case SEEK_END:
  93. if(offset > 0 || (uint64_t)(-offset) > membuf->length)
  94. return -1;
  95. membuf->pos = membuf->length + offset;
  96. break;
  97. case AVSEEK_SIZE:
  98. return membuf->length;
  99. default:
  100. return -1;
  101. }
  102. return membuf->pos;
  103. }
  104. struct PacketList {
  105. AVPacket pkt;
  106. struct PacketList *next;
  107. };
  108. struct MyStream {
  109. AVCodecContext *CodecCtx;
  110. int StreamIdx;
  111. struct PacketList *Packets;
  112. AVFrame *Frame;
  113. const uint8_t *FrameData;
  114. size_t FrameDataSize;
  115. FilePtr parent;
  116. };
  117. struct MyFile {
  118. AVFormatContext *FmtCtx;
  119. StreamPtr *Streams;
  120. size_t StreamsSize;
  121. struct MemData membuf;
  122. };
  123. static int done_init = 0;
  124. FilePtr openAVFile(const char *fname)
  125. {
  126. FilePtr file;
  127. /* We need to make sure ffmpeg is initialized. Optionally silence warning
  128. * output from the lib */
  129. if(!done_init) {av_register_all();
  130. av_log_set_level(AV_LOG_ERROR);
  131. done_init = 1;}
  132. file = (FilePtr)calloc(1, sizeof(*file));
  133. if(file && avformat_open_input(&file->FmtCtx, fname, NULL, NULL) == 0)
  134. {
  135. /* After opening, we must search for the stream information because not
  136. * all formats will have it in stream headers */
  137. if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
  138. return file;
  139. avformat_close_input(&file->FmtCtx);
  140. }
  141. free(file);
  142. return NULL;
  143. }
  144. FilePtr openAVData(const char *name, char *buffer, size_t buffer_len)
  145. {
  146. FilePtr file;
  147. if(!done_init) {av_register_all();
  148. av_log_set_level(AV_LOG_ERROR);
  149. done_init = 1;}
  150. if(!name)
  151. name = "";
  152. file = (FilePtr)calloc(1, sizeof(*file));
  153. if(file && (file->FmtCtx=avformat_alloc_context()) != NULL)
  154. {
  155. file->membuf.buffer = buffer;
  156. file->membuf.length = buffer_len;
  157. file->membuf.pos = 0;
  158. file->FmtCtx->pb = avio_alloc_context(NULL, 0, 0, &file->membuf,
  159. MemData_read, MemData_write,
  160. MemData_seek);
  161. if(file->FmtCtx->pb && avformat_open_input(&file->FmtCtx, name, NULL, NULL) == 0)
  162. {
  163. if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
  164. return file;
  165. avformat_close_input(&file->FmtCtx);
  166. }
  167. if(file->FmtCtx)
  168. avformat_free_context(file->FmtCtx);
  169. file->FmtCtx = NULL;
  170. }
  171. free(file);
  172. return NULL;
  173. }
  174. FilePtr openAVCustom(const char *name, void *user_data,
  175. int (*read_packet)(void *user_data, uint8_t *buf, int buf_size),
  176. int (*write_packet)(void *user_data, uint8_t *buf, int buf_size),
  177. int64_t (*seek)(void *user_data, int64_t offset, int whence))
  178. {
  179. FilePtr file;
  180. if(!done_init) {av_register_all();
  181. av_log_set_level(AV_LOG_ERROR);
  182. done_init = 1;}
  183. if(!name)
  184. name = "";
  185. file = (FilePtr)calloc(1, sizeof(*file));
  186. if(file && (file->FmtCtx=avformat_alloc_context()) != NULL)
  187. {
  188. file->FmtCtx->pb = avio_alloc_context(NULL, 0, 0, user_data,
  189. read_packet, write_packet, seek);
  190. if(file->FmtCtx->pb && avformat_open_input(&file->FmtCtx, name, NULL, NULL) == 0)
  191. {
  192. if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
  193. return file;
  194. avformat_close_input(&file->FmtCtx);
  195. }
  196. if(file->FmtCtx)
  197. avformat_free_context(file->FmtCtx);
  198. file->FmtCtx = NULL;
  199. }
  200. free(file);
  201. return NULL;
  202. }
  203. void clearAVAudioData(StreamPtr stream)
  204. {
  205. while(stream->Packets)
  206. {
  207. struct PacketList *self;
  208. self = stream->Packets;
  209. stream->Packets = self->next;
  210. av_free_packet(&self->pkt);
  211. av_free(self);
  212. }
  213. }
  214. void closeAVFile(FilePtr file)
  215. {
  216. size_t i;
  217. if(!file) return;
  218. for(i = 0;i < file->StreamsSize;i++)
  219. {
  220. StreamPtr stream = file->Streams[i];
  221. while(stream->Packets)
  222. {
  223. struct PacketList *self;
  224. self = stream->Packets;
  225. stream->Packets = self->next;
  226. av_free_packet(&self->pkt);
  227. av_free(self);
  228. }
  229. avcodec_close(stream->CodecCtx);
  230. av_free(stream->Frame);
  231. free(stream);
  232. }
  233. free(file->Streams);
  234. avformat_close_input(&file->FmtCtx);
  235. free(file);
  236. }
  237. int getAVFileInfo(FilePtr file, int *numaudiostreams)
  238. {
  239. unsigned int i;
  240. int audiocount = 0;
  241. if(!file) return 1;
  242. for(i = 0;i < file->FmtCtx->nb_streams;i++)
  243. {
  244. if(file->FmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
  245. audiocount++;
  246. }
  247. *numaudiostreams = audiocount;
  248. return 0;
  249. }
  250. StreamPtr getAVAudioStream(FilePtr file, int streamnum)
  251. {
  252. unsigned int i;
  253. if(!file) return NULL;
  254. for(i = 0;i < file->FmtCtx->nb_streams;i++)
  255. {
  256. if(file->FmtCtx->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
  257. continue;
  258. if(streamnum == 0)
  259. {
  260. StreamPtr stream;
  261. AVCodec *codec;
  262. void *temp;
  263. size_t j;
  264. /* Found the requested stream. Check if a handle to this stream
  265. * already exists and return it if it does */
  266. for(j = 0;j < file->StreamsSize;j++)
  267. {
  268. if(file->Streams[j]->StreamIdx == (int)i)
  269. return file->Streams[j];
  270. }
  271. /* Doesn't yet exist. Now allocate a new stream object and fill in
  272. * its info */
  273. stream = (StreamPtr)calloc(1, sizeof(*stream));
  274. if(!stream) return NULL;
  275. stream->parent = file;
  276. stream->CodecCtx = file->FmtCtx->streams[i]->codec;
  277. stream->StreamIdx = i;
  278. /* Try to find the codec for the given codec ID, and open it */
  279. codec = avcodec_find_decoder(stream->CodecCtx->codec_id);
  280. if(!codec || avcodec_open2(stream->CodecCtx, codec, NULL) < 0)
  281. {
  282. free(stream);
  283. return NULL;
  284. }
  285. /* Allocate space for the decoded data to be stored in before it
  286. * gets passed to the app */
  287. stream->Frame = avcodec_alloc_frame();
  288. if(!stream->Frame)
  289. {
  290. avcodec_close(stream->CodecCtx);
  291. free(stream);
  292. return NULL;
  293. }
  294. stream->FrameData = NULL;
  295. stream->FrameDataSize = 0;
  296. /* Append the new stream object to the stream list. The original
  297. * pointer will remain valid if realloc fails, so we need to use
  298. * another pointer to watch for errors and not leak memory */
  299. temp = realloc(file->Streams, (file->StreamsSize+1) *
  300. sizeof(*file->Streams));
  301. if(!temp)
  302. {
  303. avcodec_close(stream->CodecCtx);
  304. av_free(stream->Frame);
  305. free(stream);
  306. return NULL;
  307. }
  308. file->Streams = (StreamPtr*)temp;
  309. file->Streams[file->StreamsSize++] = stream;
  310. return stream;
  311. }
  312. streamnum--;
  313. }
  314. return NULL;
  315. }
  316. int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *type)
  317. {
  318. if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
  319. return 1;
  320. /* Get the sample type for OpenAL given the format detected by ffmpeg. */
  321. if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_U8)
  322. *type = AL_UNSIGNED_BYTE_SOFT;
  323. else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S16)
  324. *type = AL_SHORT_SOFT;
  325. else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S32)
  326. *type = AL_INT_SOFT;
  327. else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)
  328. *type = AL_FLOAT_SOFT;
  329. else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_DBL)
  330. *type = AL_DOUBLE_SOFT;
  331. else
  332. {
  333. fprintf(stderr, "Unsupported ffmpeg sample format: %s\n",
  334. av_get_sample_fmt_name(stream->CodecCtx->sample_fmt));
  335. return 1;
  336. }
  337. /* Get the OpenAL channel configuration using the channel layout detected
  338. * by ffmpeg. NOTE: some file types may not specify a channel layout. In
  339. * that case, one must be guessed based on the channel count. */
  340. if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
  341. *channels = AL_MONO_SOFT;
  342. else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_STEREO)
  343. *channels = AL_STEREO_SOFT;
  344. else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
  345. *channels = AL_QUAD_SOFT;
  346. else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
  347. *channels = AL_5POINT1_SOFT;
  348. else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
  349. *channels = AL_7POINT1_SOFT;
  350. else if(stream->CodecCtx->channel_layout == 0)
  351. {
  352. /* Unknown channel layout. Try to guess. */
  353. if(stream->CodecCtx->channels == 1)
  354. *channels = AL_MONO_SOFT;
  355. else if(stream->CodecCtx->channels == 2)
  356. *channels = AL_STEREO_SOFT;
  357. else
  358. {
  359. fprintf(stderr, "Unsupported ffmpeg raw channel count: %d\n",
  360. stream->CodecCtx->channels);
  361. return 1;
  362. }
  363. }
  364. else
  365. {
  366. char str[1024];
  367. av_get_channel_layout_string(str, sizeof(str), stream->CodecCtx->channels,
  368. stream->CodecCtx->channel_layout);
  369. fprintf(stderr, "Unsupported ffmpeg channel layout: %s\n", str);
  370. return 1;
  371. }
  372. *rate = stream->CodecCtx->sample_rate;
  373. return 0;
  374. }
  375. /* Used by getAV*Data to search for more compressed data, and buffer it in the
  376. * correct stream. It won't buffer data for streams that the app doesn't have a
  377. * handle for. */
  378. static int getNextPacket(FilePtr file, int streamidx)
  379. {
  380. struct PacketList *packet;
  381. packet = (struct PacketList*)av_malloc(sizeof(*packet));
  382. packet->next = NULL;
  383. next_packet:
  384. while(av_read_frame(file->FmtCtx, &packet->pkt) >= 0)
  385. {
  386. StreamPtr *iter = file->Streams;
  387. StreamPtr *iter_end = iter + file->StreamsSize;
  388. /* Check each stream the user has a handle for, looking for the one
  389. * this packet belongs to */
  390. while(iter != iter_end)
  391. {
  392. if((*iter)->StreamIdx == packet->pkt.stream_index)
  393. {
  394. struct PacketList **last;
  395. last = &(*iter)->Packets;
  396. while(*last != NULL)
  397. last = &(*last)->next;
  398. *last = packet;
  399. if((*iter)->StreamIdx == streamidx)
  400. return 1;
  401. packet = (struct PacketList*)av_malloc(sizeof(*packet));
  402. packet->next = NULL;
  403. goto next_packet;
  404. }
  405. iter++;
  406. }
  407. /* Free the packet and look for another */
  408. av_free_packet(&packet->pkt);
  409. }
  410. av_free(packet);
  411. return 0;
  412. }
  413. uint8_t *getAVAudioData(StreamPtr stream, size_t *length)
  414. {
  415. int got_frame;
  416. int len;
  417. if(length) *length = 0;
  418. if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
  419. return NULL;
  420. next_packet:
  421. if(!stream->Packets && !getNextPacket(stream->parent, stream->StreamIdx))
  422. return NULL;
  423. /* Decode some data, and check for errors */
  424. avcodec_get_frame_defaults(stream->Frame);
  425. while((len=avcodec_decode_audio4(stream->CodecCtx, stream->Frame,
  426. &got_frame, &stream->Packets->pkt)) < 0)
  427. {
  428. struct PacketList *self;
  429. /* Error? Drop it and try the next, I guess... */
  430. self = stream->Packets;
  431. stream->Packets = self->next;
  432. av_free_packet(&self->pkt);
  433. av_free(self);
  434. if(!stream->Packets)
  435. goto next_packet;
  436. }
  437. if(len < stream->Packets->pkt.size)
  438. {
  439. /* Move the unread data to the front and clear the end bits */
  440. int remaining = stream->Packets->pkt.size - len;
  441. memmove(stream->Packets->pkt.data, &stream->Packets->pkt.data[len],
  442. remaining);
  443. memset(&stream->Packets->pkt.data[remaining], 0,
  444. stream->Packets->pkt.size - remaining);
  445. stream->Packets->pkt.size -= len;
  446. }
  447. else
  448. {
  449. struct PacketList *self;
  450. self = stream->Packets;
  451. stream->Packets = self->next;
  452. av_free_packet(&self->pkt);
  453. av_free(self);
  454. }
  455. if(!got_frame || stream->Frame->nb_samples == 0)
  456. goto next_packet;
  457. /* Set the output buffer size */
  458. *length = av_samples_get_buffer_size(NULL, stream->CodecCtx->channels,
  459. stream->Frame->nb_samples,
  460. stream->CodecCtx->sample_fmt, 1);
  461. return stream->Frame->data[0];
  462. }
  463. size_t readAVAudioData(StreamPtr stream, void *data, size_t length)
  464. {
  465. size_t dec = 0;
  466. if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
  467. return 0;
  468. while(dec < length)
  469. {
  470. /* If there's no decoded data, find some */
  471. if(stream->FrameDataSize == 0)
  472. {
  473. stream->FrameData = getAVAudioData(stream, &stream->FrameDataSize);
  474. if(!stream->FrameData)
  475. break;
  476. }
  477. if(stream->FrameDataSize > 0)
  478. {
  479. /* Get the amount of bytes remaining to be written, and clamp to
  480. * the amount of decoded data we have */
  481. size_t rem = length-dec;
  482. if(rem > stream->FrameDataSize)
  483. rem = stream->FrameDataSize;
  484. /* Copy the data to the app's buffer and increment */
  485. if(data != NULL)
  486. {
  487. memcpy(data, stream->FrameData, rem);
  488. data = (char*)data + rem;
  489. }
  490. dec += rem;
  491. /* If there's any decoded data left, move it to the front of the
  492. * buffer for next time */
  493. stream->FrameData += rem;
  494. stream->FrameDataSize -= rem;
  495. }
  496. }
  497. /* Return the number of bytes we were able to get */
  498. return dec;
  499. }
  500. void *decodeAVAudioStream(StreamPtr stream, size_t *length)
  501. {
  502. char *outbuf = NULL;
  503. size_t buflen = 0;
  504. void *inbuf;
  505. size_t got;
  506. *length = 0;
  507. if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
  508. return NULL;
  509. while((inbuf=getAVAudioData(stream, &got)) != NULL && got > 0)
  510. {
  511. void *ptr;
  512. ptr = realloc(outbuf, NextPowerOf2(buflen+got));
  513. if(ptr == NULL)
  514. break;
  515. outbuf = (char*)ptr;
  516. memcpy(&outbuf[buflen], inbuf, got);
  517. buflen += got;
  518. }
  519. outbuf = (char*)realloc(outbuf, buflen);
  520. *length = buflen;
  521. return outbuf;
  522. }