PageRenderTime 61ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/FFmpegPlayTest/FFmpegPlayTest/FFDecoder.m

https://bitbucket.org/jackode/ffmpeg-examples
Objective C | 1231 lines | 697 code | 208 blank | 326 comment | 94 complexity | 05202dcf7d6d7ccfba5bd5651f1a30e5 MD5 | raw file
  1. //
  2. // FFPDecoder.m
  3. // FFmpegPlayTest
  4. //
  5. // Created by Jack on 11/2/12.
  6. // Copyright (c) 2012 Jack. All rights reserved.
  7. //
  8. #import <CoreAudio/CoreAudioTypes.h>
  9. #import "FFDecoder.h"
  10. #ifdef DEBUG_DECODER
  11. #define JLogDec JLog
  12. #else
  13. #define JLogDec(...)
  14. #endif
  15. #ifdef DEBUG_AUDIO
  16. #define JLogAudio JLog
  17. #else
  18. #define JLogAudio(...)
  19. #endif
  20. #ifdef DEBUG_VIDEO
  21. #define JLogVideo JLog
  22. #else
  23. #define JLogVideo(...)
  24. #endif
  25. #ifdef DEBUG_DEMUX
  26. #define JLogDmx JLog
  27. #else
  28. #define JLogDmx(...)
  29. #endif
  30. /// Use another thread to decode audio and add it to
  31. /// the audio buffer
  32. //#define USE_AUDIO_THREAD
  33. //#define _cplusplus
  34. #define kFFMaxVideoQueueSize (5 * 256 * 1024) // ~ 1MB
  35. #define kFFMaxAudioQueueSize (5 * 16 * 1024)
  36. #define AUDIO_DIFF_AVG_NB 20
  37. #define SDL_AUDIO_BUFFER_SIZE 1024
  38. #define SAMPLE_CORRECTION_PERCENT_MAX 10.0
  39. #define AV_NOSYNC_THRESHOLD 10.0
  40. #define AV_SYNC_THRESHOLD 0.01
  41. #define AV_SYNC_VIDEO_THRESHOLD 0.01
  42. #define AUDIO_DIFF_AVG_NB 20
  43. #define kFFDecodeKeyVideoPktPts @"videoPacketPts"
  44. /**
  45. This function should return TRUE (1) if the decode process is quited
  46. otherwise return FALSE (0)
  47. Usage: check status to see if "quit signal" has sent, if so return 1
  48. to interupt IO process.
  49. */
  50. static int decodeInteruptCallback(void * ctx) {
  51. int* status = (int*) ctx;
  52. return (*status == FFDecodeStateStopped);
  53. }
  54. double global_video_pkt_pts;
  55. int our_get_buffer(struct AVCodecContext *c, AVFrame *pic) {
  56. int ret = avcodec_default_get_buffer(c, pic);
  57. uint64_t *pts = av_malloc(sizeof(uint64_t));
  58. *pts = global_video_pkt_pts;
  59. pic->opaque = pts;
  60. return ret;
  61. }
  62. //---------------------------------------------------------------------
  63. void our_release_buffer(struct AVCodecContext *c, AVFrame *pic) {
  64. if(pic) av_freep(&pic->opaque);
  65. avcodec_default_release_buffer(c, pic);
  66. }
  67. #pragma mark - FFDecoder Extension
  68. @interface FFDecoder ()
  69. {
  70. }
  71. @end
  72. #pragma mark - FFDecoder Implementation
  73. @implementation FFDecoder
  74. @synthesize clockMode=_clockMode;
  75. #pragma mark Init and utilities
  76. - (id) initWithContentURL: (NSURL*) url
  77. {
  78. self = [super init];
  79. if (self) {
  80. [[FFMpegEngine shareInstance] initFFmpegEngine];
  81. // Assign callback to check status of decode process
  82. AVIOInterruptCB interuptCallback;
  83. interuptCallback.callback = decodeInteruptCallback;
  84. interuptCallback.opaque = &decodeStatus;
  85. decodeStatus = FFDecodeStateUnknown;
  86. // Open video file and assign ffmpeg io interupt callback
  87. _video = [[FFVideo alloc] initWithUrl: url
  88. interuptCallback: interuptCallback];
  89. if (!_video) {
  90. JLogDec(@"Failed init decoder");
  91. return nil;
  92. }
  93. [_video videoCodecContext]->get_buffer = our_get_buffer;
  94. [_video videoCodecContext]->release_buffer = our_release_buffer;
  95. // Using ffmpeg for audio decoding
  96. decodeAudioMode = FFDecodeAudioModeFFmpeg;
  97. //decodeAudioMode = FFDecodeAudioModeNative; // TEST
  98. _clockMode = FFDecodeMasterClockExternal;
  99. // For the current version, we force output of decoder
  100. // to be RGB_565, for the later update this value should
  101. // be set via a public accessor
  102. glPixelFormat = GL_UNSIGNED_SHORT_5_6_5;
  103. // [JACK] Test directly render YUV420
  104. // ffPixelFormat = PIX_FMT_RGB565;
  105. ffPixelFormat = PIX_FMT_YUV420P;
  106. // TODO: remmeber to release swsScale
  107. // Init software scale context
  108. swsContext = sws_getContext([_video videoCodecContext]->width,
  109. [_video videoCodecContext]->height,
  110. [_video videoCodecContext]->pix_fmt,
  111. [_video videoCodecContext]->width,
  112. [_video videoCodecContext]->height,
  113. ffPixelFormat, // match with outputPixelFormat
  114. SWS_FAST_BILINEAR,
  115. NULL, NULL, NULL);
  116. if (![self initDecoder])
  117. {
  118. JLogDec(@"Failed init decoder");
  119. return nil;
  120. }
  121. videoOn = YES;
  122. audioOn = YES;
  123. decodeStatus |= FFDecodeStateInited;
  124. }
  125. return self;
  126. }
  127. //----------------------------------------------------------------
  128. - (BOOL) initDecoder
  129. {
  130. BOOL ret = TRUE;
  131. // >> VIDEO <<<
  132. // Initialize video queue buffer
  133. _videoPktQueue = [[FFAVPacketQueue alloc] initWithSize:kFFMaxVideoQueueSize];
  134. _videoPicQueue = [[FFPictureQueue alloc] init]; // using fixed size queue
  135. if(!_videoPicQueue || !_videoPktQueue)
  136. {
  137. ret = FALSE;
  138. goto finish;
  139. }
  140. startTime = CACurrentMediaTime();
  141. // Initialize timer variable
  142. videoFrameTimer = CACurrentMediaTime();
  143. videoFrameLastDelay = 40e-3;
  144. videoFrameLastPts = 0;
  145. videoClock = 0;
  146. videoCurrentPts = 0;
  147. videoCurrentPtsTime = CACurrentMediaTime();
  148. // >>> AUDIO <<<
  149. // Initialize audio buffer queue
  150. _audioPktQueue = [[FFAVPacketQueue alloc] initWithSize:kFFMaxAudioQueueSize];
  151. if (!_audioPktQueue) {
  152. ret = FALSE;
  153. goto finish;
  154. }
  155. UInt32 bitPerChannel = [FFMpegEngine bitsForSampleFormat: [_video audioCodecContext]->sample_fmt];
  156. BOOL isNonInterleaved = NO;
  157. UInt32 channelsPerSample = [_video audioCodecContext]->channels;
  158. Float64 sampleRate = [_video audioCodecContext]->sample_rate;
  159. UInt32 mBytesPerFrame = (isNonInterleaved ? 1 : channelsPerSample) * (bitPerChannel/8);
  160. // Init audio buffer for decoded audio frames
  161. _audioBuffer = [[FFAudioBuffer alloc] initBufferForDuration: 1
  162. bytesPerSample: mBytesPerFrame
  163. sampleRate: sampleRate];
  164. // Initialize audio clock
  165. audioClock = 0;
  166. // TODO: define when decoder connect to audio speaker
  167. audioHWBufferSpec = 0;
  168. // Initialize audio sync accumulator
  169. audioDiffCum = 0;
  170. audioDiffAverageCoef = exp(log(0.01 / AUDIO_DIFF_AVG_NB));
  171. audioDiffAverageCount = 0;
  172. audioDiffThreshold= 2.0 * SDL_AUDIO_BUFFER_SIZE / [_video audioCodecContext]->sample_rate;
  173. memset(&pktFromQueue, 0, sizeof(pktFromQueue));
  174. memset(&pktTemp, 0, sizeof(pktTemp));
  175. finish:
  176. if (!ret){
  177. JLogDec(@"Failed to init decoder");
  178. }
  179. else{
  180. JLogDec(@"Finished init decoder");
  181. }
  182. return ret;
  183. }
  184. //----------------------------------------------------------------
  185. #pragma mark FFControllable Protocol
  186. //----------------------------------------------------------------
  187. - (void) pause
  188. {
  189. //TODO: Implement
  190. JLogDec(@"Decoder Paused");
  191. }
  192. - (void) resume
  193. {
  194. JLogDec(@"Decoder Resumed");
  195. }
  196. //----------------------------------------------------------------
  197. - (BOOL) isReady
  198. {
  199. return ((decodeStatus & FFDecodeStateInited) | (decodeStatus & FFDecodeStatePaused)) != 0 ;
  200. }
  201. //----------------------------------------------------------------
  202. - (void) start
  203. {
  204. //[self performSelectorInBackground:@selector(demuxVideo:) withObject:self];
  205. demuxThread = [[NSThread alloc] initWithTarget:self
  206. selector:@selector(demuxVideo:)
  207. object:self];
  208. decodeVideoThread = [[NSThread alloc] initWithTarget:self
  209. selector:@selector(decodeVideo:)
  210. object:self];
  211. decodeAudioThread = [[NSThread alloc] initWithTarget:self
  212. selector:@selector(decodeAudio:)
  213. object:self];
  214. [demuxThread start];
  215. if (videoOn) {
  216. [decodeVideoThread start];
  217. }
  218. if (audioOn) {
  219. [decodeAudioThread start];
  220. }
  221. startTime = CACurrentMediaTime();;
  222. decodeStatus = FFDecodeStateDecoding;
  223. JLogDec(@"Decoder started");
  224. }
  225. //----------------------------------------------------------------
  226. - (void) stop
  227. {
  228. //TODO: Implement
  229. if (demuxThread) {
  230. [demuxThread cancel];
  231. }
  232. if (decodeVideoThread && [decodeVideoThread isExecuting]) {
  233. [decodeVideoThread cancel];
  234. }
  235. if (decodeAudioThread && [decodeAudioThread isExecuting]) {
  236. [decodeAudioThread cancel];
  237. }
  238. JLogDec(@"Decoder Stopped");
  239. }
  240. //----------------------------------------------------------------
  241. - (BOOL) isRuning
  242. {
  243. //TODO: Implement
  244. return NO;
  245. }
  246. #pragma mark Decoding Threads
  247. - (void) demuxVideo: (id) data
  248. {
  249. @autoreleasepool {
  250. NSThread* currentThread = [NSThread currentThread];
  251. AVPacket readPkt, *pReadPkt = &readPkt;
  252. AVFormatContext* pContext = [_video formatContext];
  253. for (;;) {
  254. /// Check if thread is cancelled, OR ***decode finish***
  255. if ([currentThread isCancelled]) {
  256. JLogDmx(@"Demux thread cancelled");
  257. // TODO: release resource and allocated memory here
  258. break;
  259. }
  260. // TODO: Handle seeking stuff here
  261. // flush queue, push the flush pkt to queue
  262. // Check if pkt queue data size is exceed the limit,
  263. // if so delay, than continue to next loop
  264. // if ([_videoPktQueue dataSize] > kFFMaxVideoQueueSize||
  265. // [_audioPktQueue dataSize] > kFFMaxAudioQueueSize)
  266. // {
  267. // JLogDmx(@"Waiting for space in packet queue");
  268. // usleep(10000); // delay for 10 miliseconds
  269. // continue;
  270. // }
  271. if (av_read_frame(pContext, pReadPkt) < 0) {
  272. if (&pContext->pb && &pContext->pb->error) {
  273. // NO Error, wait for user input to interrupt.
  274. usleep(10000);
  275. continue;
  276. }else{
  277. break;
  278. }
  279. }
  280. // Push packet into corresponding queue
  281. if (pReadPkt->stream_index == [_video videoStreamIndex]) {
  282. if(videoOn){
  283. JLogDmx(@"Push packet to video queue");
  284. //NSLog(@"V---");
  285. [_videoPktQueue pushPacket:pReadPkt blocked:YES];
  286. }else{
  287. av_free_packet(pReadPkt);
  288. }
  289. }else if(pReadPkt->stream_index == [_video audioStreamIndex]){
  290. if (audioOn) {
  291. JLogDmx(@"Push packet to audio queue");
  292. //NSLog(@"---A");
  293. //NSLog(@"Pkt'size: %d, duration: %d, dts: %lld", pReadPkt->size, pReadPkt->duration, pReadPkt->pts);
  294. [_audioPktQueue pushPacket:pReadPkt blocked:YES];
  295. }else{
  296. av_free_packet(pReadPkt);
  297. }
  298. }else{
  299. av_free_packet(pReadPkt);
  300. }
  301. }
  302. /// ???: Why do have to wait for cancelled signal, why dont just finish
  303. /// the thread routine?
  304. // Wait for the quit signal
  305. while (![currentThread isCancelled]) {
  306. usleep(100000);
  307. }
  308. }
  309. JLogDec(@"Demux thread finished");
  310. }
  311. //----------------------------------------------------------------
  312. - (void) decodeVideo: (id) data
  313. {
  314. JLogDec(@"Decoding video stream");
  315. @autoreleasepool {
  316. AVCodecContext* pVideoCodecCtx = [_video videoCodecContext];
  317. NSThread* currentThread = [NSThread currentThread];
  318. AVPacket readPkt, *pReadPkt = &readPkt;
  319. AVFrame* pFrame;
  320. int frameFinished;
  321. NSTimeInterval pts;
  322. int videoWidth = [_video videoCodecContext]->width;
  323. int videoHeight = [_video videoCodecContext]->height;
  324. JLogVideo(@"Video width: %d, height: %d", videoWidth, videoHeight);
  325. pFrame = avcodec_alloc_frame();
  326. for (;;) {
  327. /// Check if thread is cancelled
  328. if ([currentThread isCancelled]) {
  329. JLogVideo(@"Decode video thread cancelled");
  330. break;
  331. }
  332. /// Get pkt from queue
  333. if (![_videoPktQueue popPacket:pReadPkt blocked:YES]) {
  334. JLogVideo(@"Get no packet from video queue");
  335. continue;
  336. }
  337. /* TODO: Handle seeking packet
  338. if(packet->data == flush_pkt.data) {
  339. avcodec_flush_buffers(vidState->video_st->codec);
  340. continue;
  341. }
  342. */
  343. pts = 0;
  344. global_video_pkt_pts = pReadPkt->pts;
  345. // Decode video frame, memory will be allocate automatically for pFrame
  346. avcodec_decode_video2(pVideoCodecCtx, pFrame, &frameFinished, pReadPkt);
  347. if(pReadPkt->dts == AV_NOPTS_VALUE
  348. && pFrame->opaque && *(uint64_t*)pFrame->opaque != AV_NOPTS_VALUE) {
  349. pts = *(uint64_t *)pFrame->opaque;
  350. } else if(pReadPkt->dts != AV_NOPTS_VALUE) {
  351. pts = pReadPkt->dts;
  352. } else {
  353. pts = 0;
  354. }
  355. pts *= av_q2d([_video videoStream]->time_base);
  356. //JLogVideo(@"Picture pts before sync: %f", pts);
  357. // Decoded a frame?
  358. if (frameFinished) {
  359. JLogVideo(@"Got a frame");
  360. // [TEST] Dont adjust video pts
  361. pts = [self synchronizeVideoFrame:pFrame
  362. framePts:pts];
  363. //JLogVideo(@"Picture pts after sync: %f", pts);
  364. // Reuse picture in the queue
  365. FFVideoPicture* picture = [_videoPicQueue pictureToWriteWithBlock:YES];
  366. // If it NULL, reallocate the new one
  367. if (!picture) {
  368. picture = [[FFVideoPicture alloc] initWithPixelFormat:ffPixelFormat
  369. width:videoWidth
  370. height:videoHeight];
  371. }
  372. // JLogVideo(@"Source video pix format: %d", [_video videoCodecContext]->pix_fmt);
  373. /// Convert frame data format to picture's format
  374. // get AVPicture instance of the picture which using the same
  375. // picture data
  376. // AVPicture* avPict = [picture avPicture];
  377. // JLogVideo(@"avPict data: %p", avPict->data);
  378. // JLogVideo(@"avPict data 0: %p", avPict->data[0]);
  379. // JLogVideo(@"avPict data 1: %p", avPict->data[1]);
  380. // JLogVideo(@"avPict data 2: %p", avPict->data[2]);
  381. /// [JACK] Test no sws pixel convert
  382. // sws_scale(swsContext,
  383. // (const uint8_t * const *)pFrame->data,
  384. // pFrame->linesize,
  385. // 0,
  386. // videoHeight,
  387. // avPict->data,
  388. // avPict->linesize);
  389. av_picture_copy([picture avPicture],
  390. (const AVPicture*) pFrame,
  391. [_video videoCodecContext]->pix_fmt,
  392. videoWidth,
  393. videoHeight);
  394. // Update picture pts
  395. [picture setPts:pts];
  396. /// Push frame to picture queue
  397. [_videoPicQueue pushPicture:picture blockingMode:YES];
  398. }
  399. av_free_packet(pReadPkt);
  400. }
  401. av_free(pFrame);
  402. JLogVideo(@"Decode video finished");
  403. while (![currentThread isCancelled]) {
  404. usleep(100000);
  405. }
  406. }
  407. }
  408. //----------------------------------------------------------------
  409. /**
  410. Right now the audio is decoded immediately when it's requested from
  411. audio handler, so decodeAudio:data virtually does nothing. The code
  412. is kept for reference.
  413. */
  414. - (void) decodeAudio: (id) data
  415. {
  416. #ifdef USE_AUDIO_THREAD
  417. @autoreleasepool {
  418. AVCodecContext* pAudioCodecCtx = [_video audioCodecContext];
  419. NSThread* currentThread = [NSThread currentThread];
  420. int decodedLen, decodedFrameSize;
  421. AVPacket readPkt;
  422. AVPacket *pReadPkt = &readPkt;
  423. AVPacket pktTemp;
  424. AVPacket *pPktTemp = &pktTemp; // hold data that is being process.
  425. AVFrame *pDecodedFrame;
  426. pDecodedFrame = avcodec_alloc_frame();
  427. avcodec_get_frame_defaults(pDecodedFrame);
  428. // Zero out temporary packet
  429. memset(pPktTemp, 0, sizeof(AVPacket));
  430. memset(pReadPkt, 0, sizeof(AVPacket));
  431. // Loop that decode audio packets and push decode data to audio buffer
  432. JLogAudio(@"Decoding audio stream");
  433. for (;;) {
  434. // Check if thread is cancelled
  435. if ([currentThread isCancelled]) {
  436. JLogAudio(@"Decode audio thread cancelled");
  437. break;
  438. }
  439. // A packet may contain more than one frame, so to decode a packet
  440. // we need a loop
  441. while(pktTemp.size > 0){
  442. int gotFrame = 0;
  443. //avcodec_get_frame_defaults(&decodedFrame);
  444. // Decode audio data to decoded frame
  445. decodedLen = avcodec_decode_audio4(pAudioCodecCtx,
  446. pDecodedFrame,
  447. &gotFrame,
  448. pPktTemp);
  449. // If error occur, we skip the packet
  450. if (decodedLen < 0) {
  451. pPktTemp->size = 0;
  452. break;
  453. }
  454. // Update pointer and length in temp packet
  455. pPktTemp->data += decodedLen;
  456. pPktTemp->size -= decodedLen;
  457. // If a frame is found
  458. if (gotFrame) {
  459. // Calculate size in bytes for decoded frames
  460. decodedFrameSize = av_samples_get_buffer_size(NULL, pAudioCodecCtx->channels,
  461. pDecodedFrame->nb_samples,
  462. pAudioCodecCtx->sample_fmt, 1);
  463. /// FIXME: this push will be call so frequently so it will block access
  464. /// to the audio buffer so often that will flicking noise in audio output
  465. // Push those data to buffer
  466. [_audioBuffer pushSample:pDecodedFrame->data[0]
  467. size:decodedFrameSize
  468. blocked:YES];
  469. }
  470. };
  471. // Free packet after decode it
  472. if(pReadPkt->data)
  473. av_free_packet(pReadPkt);
  474. // Get next pkt from queue
  475. if (![_audioPktQueue popPacket:pReadPkt blocked:YES]) {
  476. JLogAudio(@"Get no packet from audio queue");
  477. continue;
  478. }
  479. // TODO: Handleflush packets
  480. //if(pkt->data == flush_pkt.data) {
  481. // avcodec_flush_buffers(vidState->audio_st->codec);
  482. // continue;
  483. //}
  484. // Assign data to temporary packet
  485. pktTemp.data = pReadPkt->data;
  486. pktTemp.size = pReadPkt->size;
  487. /* if update, update the audio clock w/pts */
  488. //if(pkt->pts != AV_NOPTS_VALUE) {
  489. // vidState->audio_clock = av_q2d(vidState->audio_st->time_base) * pkt->pts;
  490. //}
  491. }
  492. avcodec_free_frame(&pDecodedFrame);
  493. }
  494. return;
  495. #endif
  496. }
  497. //----------------------------------------------------------------
  498. #pragma mark - Utilities Methods
  499. - (NSTimeInterval) masterClock
  500. {
  501. if (_clockMode == FFDecodeMasterClockVideo) {
  502. return [self videoClock];
  503. }else if (_clockMode == FFDecodeMasterClockAudio){
  504. return [self audioClock];
  505. }else{
  506. return [self externalClock];
  507. }
  508. }
  509. //-----------------------------------------------------------------
  510. - (NSTimeInterval) audioClock
  511. {
  512. double pts;
  513. int hw_buf_size, bytes_per_sec, n;
  514. pts = audioClock; /* maintained in the audio thread */
  515. hw_buf_size = audioBufSize - audioBufIndex;
  516. bytes_per_sec = 0;
  517. n = [_video audioCodecContext]->channels * 2;
  518. if([_video audioStream]) {
  519. bytes_per_sec = [_video audioCodecContext]->sample_rate * n;
  520. }
  521. if(bytes_per_sec) {
  522. pts -= (double)hw_buf_size / bytes_per_sec;
  523. }
  524. return pts;
  525. }
  526. //-----------------------------------------------------------------
  527. - (NSTimeInterval) videoClock
  528. {
  529. double delta;
  530. delta = CACurrentMediaTime() - videoCurrentPtsTime;
  531. return videoCurrentPts + delta;
  532. }
  533. //-----------------------------------------------------------------
  534. - (NSTimeInterval) externalClock
  535. {
  536. return CACurrentMediaTime() -startTime;
  537. }
  538. //-----------------------------------------------------------------
  539. - (NSTimeInterval) synchronizeVideoFrame: (AVFrame*) srcFrame
  540. framePts: (NSTimeInterval) pts
  541. {
  542. NSTimeInterval frameDelay;
  543. if(pts != 0) {
  544. /* if we have pts, set video clock to it */
  545. videoClock = pts;
  546. } else {
  547. /* if we aren't given a pts, set it to the clock */
  548. pts = videoClock;
  549. }
  550. /* update the video clock */
  551. frameDelay = av_q2d([_video videoStream]->codec->time_base);
  552. /* if we are repeating a frame, adjust clock accordingly */
  553. frameDelay += srcFrame->repeat_pict * (frameDelay * 0.5);
  554. videoClock += frameDelay;
  555. return pts;
  556. }
  557. //----------------------------------------------------------------
  558. /**
  559. decode audio to audio buffer and store audio of first sample of
  560. new decoded audio sample
  561. */
  562. - (int) decodeAudioOutBuff: (NSTimeInterval*) pts
  563. {
  564. AVCodecContext* pAudioCodecCtx = [_video audioCodecContext];
  565. AVStream* pAudioStream = [_video audioStream];
  566. int decodedLen =0 , decodedFrameSize =0 , n = 0;
  567. AVFrame *pDecodedFrame = nil;
  568. pDecodedFrame = avcodec_alloc_frame();
  569. avcodec_get_frame_defaults(pDecodedFrame);
  570. // Loop that decode audio packets and push decode data to audio buffer
  571. JLogAudio(@"Decoding audio stream");
  572. for (;;) {
  573. // A packet may contain more than one frame, so to decode a packet
  574. // we need a loop
  575. while(pktTemp.size > 0){
  576. int gotFrame = 0;
  577. //avcodec_get_frame_defaults(&decodedFrame);
  578. // Decode audio data to decoded frame
  579. decodedLen = avcodec_decode_audio4(pAudioCodecCtx,
  580. pDecodedFrame,
  581. &gotFrame,
  582. &pktTemp);
  583. // If error occur, we skip the packet
  584. if (decodedLen < 0) {
  585. pktTemp.size = 0;
  586. break;
  587. }
  588. // Update pointer and length in temp packet
  589. pktTemp.data += decodedLen;
  590. pktTemp.size -= decodedLen;
  591. // If a frame is found
  592. if (gotFrame) {
  593. // Calculate size in bytes for decoded frames
  594. decodedFrameSize = av_samples_get_buffer_size(NULL, pAudioCodecCtx->channels,
  595. pDecodedFrame->nb_samples,
  596. pAudioCodecCtx->sample_fmt, 1);
  597. // we got decode data pointed by decodedFrame.data[0], with size
  598. // decodedFrameSize
  599. memcpy(audioBuffer, pDecodedFrame->data[0], decodedFrameSize);
  600. }else{
  601. decodedFrameSize = 0;
  602. }
  603. if (decodedFrameSize <= 0) {
  604. continue;
  605. }
  606. *pts = audioClock;
  607. n = 2 * pAudioCodecCtx->channels; // 16bits per sample per channel
  608. audioClock += (double)decodedFrameSize / (double)(n * pAudioCodecCtx->sample_rate);
  609. // decodedFrameSize > 0;
  610. break;
  611. }
  612. // If got data, break and return
  613. if (decodedFrameSize > 0) {
  614. break;
  615. }
  616. // Free packet after decode it
  617. if(pktFromQueue.data)
  618. av_free_packet(&pktFromQueue);
  619. // TODO: detect quit signal
  620. // Get next pkt from queue
  621. if (![_audioPktQueue popPacket:&pktFromQueue blocked:YES]) {
  622. JLogAudio(@"Get no packet from audio queue");
  623. return -1;
  624. }
  625. // TODO: Handleflush packets
  626. //if(pkt->data == flush_pkt.data) {
  627. // avcodec_flush_buffers(vidState->audio_st->codec);
  628. // continue;
  629. //}
  630. // Assign data to temporary packet
  631. pktTemp.data = pktFromQueue.data;
  632. pktTemp.size = pktFromQueue.size;
  633. /* if update, update the audio clock w/pts */
  634. if(pktFromQueue.pts != AV_NOPTS_VALUE) {
  635. audioClock = av_q2d(pAudioStream->time_base) * pktFromQueue.pts;
  636. }
  637. }
  638. avcodec_free_frame(&pDecodedFrame);
  639. return decodedFrameSize;
  640. }
  641. //----------------------------------------------------------------
  642. - (int) synchronizeAudioBuff: (int16_t *) pBuf
  643. OfSize: (int) auSize
  644. pts: (double) pts
  645. {
  646. AVCodecContext* pAudioCodecCtx = [_video audioCodecContext];
  647. int n = 2 * pAudioCodecCtx->channels;
  648. double refClock;
  649. double diff, avg_diff;
  650. int wanted_size, min_size, max_size;
  651. if (_clockMode != FFDecodeMasterClockAudio) {
  652. refClock = [self masterClock];
  653. diff = [self audioClock] - refClock;
  654. JLogDec(@"A-Ref diff: %f", diff);
  655. /*
  656. if (diff < AV_NOSYNC_THRESHOLD) {
  657. audioDiffCum = diff + audioDiffAverageCoef * audioDiffCum;
  658. JLogDec(@"DiffCum: %f, avgCount: %d", audioDiffCum, audioDiffAverageCount);
  659. if (audioDiffAverageCount < AUDIO_DIFF_AVG_NB) {
  660. audioDiffAverageCount++;
  661. }else{
  662. avg_diff = audioDiffCum * (1.0 - audioDiffAverageCoef);
  663. JLogDec(@"New avg: %f, threshold: %f", avg_diff, audioDiffThreshold);
  664. if (fabs(avg_diff) >= audioDiffThreshold) {
  665. wanted_size = auSize + ((int)(diff * pAudioCodecCtx->sample_rate) * n);
  666. min_size = (float) auSize * ((100.0 - SAMPLE_CORRECTION_PERCENT_MAX) / 100.0);
  667. max_size = (float) auSize * ((100.0 + SAMPLE_CORRECTION_PERCENT_MAX) / 100.0);
  668. JLogDec(@"wanted size: %d, max: %d, min: %d", wanted_size, max_size, min_size);
  669. if (wanted_size < min_size)
  670. {
  671. wanted_size = min_size;
  672. }
  673. else if(wanted_size > max_size)
  674. {
  675. wanted_size = max_size;
  676. }
  677. else if (wanted_size > auSize)
  678. {
  679. uint8_t *sampleEnd, *q;
  680. int nb;
  681. nb = auSize - wanted_size;
  682. sampleEnd = (uint8_t*) pBuf + auSize - n;
  683. q = sampleEnd + n;
  684. while(nb > 0) {
  685. memcpy(q, sampleEnd, n);
  686. q += n;
  687. nb -= n;
  688. }
  689. auSize = wanted_size;
  690. }
  691. }
  692. }
  693. }else{
  694. audioDiffAverageCount = 0;
  695. audioDiffCum = 0;
  696. }
  697. */
  698. }
  699. JLogDec(@"Return auSize: %d", auSize);
  700. return auSize;
  701. }
  702. //----------------------------------------------------------------
  703. /**
  704. Decode audio samples to pBuffer, given size of buffer and pts of the
  705. buffer
  706. @param pBuffer Pointer to the buffer
  707. @param capacity size of buffer
  708. @param pts Presenting timestamp of the buffer
  709. @return return filled size
  710. */
  711. - (void) fillPCMAudioIntoBuff:(void *) pBuffer
  712. capacity:(UInt32) capacity
  713. {
  714. int needRead = capacity;
  715. int audioSize, copySize;
  716. double pts;
  717. while (needRead > 0) {
  718. // if there is no samples in audio buffer, decode new samples
  719. if(audioBufIndex >= audioBufSize){
  720. audioSize = [self decodeAudioOutBuff:&pts];
  721. //JLogDec(@"Audio size before: %d", audioSize);
  722. if (audioSize < 0) {
  723. audioBufSize = 1024;
  724. memset(audioBuffer, 0, audioBufSize);
  725. }else{
  726. // audioSize = [self synchronizeAudioBuff: (int16_t*)audioBuffer
  727. // OfSize: audioSize
  728. // pts: pts];
  729. //JLogDec(@"Audio size after: %d", audioSize);
  730. audioBufSize = audioSize;
  731. }
  732. audioBufIndex = 0;
  733. }
  734. copySize = audioBufSize - audioBufIndex;
  735. if (copySize > needRead) {
  736. copySize = needRead;
  737. }
  738. memcpy(pBuffer, audioBuffer + audioBufIndex, copySize);
  739. needRead -= copySize;
  740. pBuffer += copySize;
  741. audioBufIndex += copySize;
  742. }
  743. }
  744. //----------------------------------------------------------------
  745. - (void) fillAudioPktToBuff: (AudioQueueBufferRef)aqBuffer
  746. forPts: (NSTimeInterval) pts
  747. {
  748. int ret = 0;
  749. while ((aqBuffer->mAudioDataByteSize < aqBuffer->mAudioDataBytesCapacity) &&
  750. aqBuffer->mPacketDescriptionCount < aqBuffer->mPacketDescriptionCapacity)
  751. {
  752. ret = [_audioPktQueue popPacket:&pktFromQueue blocked:YES];
  753. if (ret == 0) {
  754. break;
  755. }
  756. memcpy(aqBuffer->mAudioData + aqBuffer->mAudioDataByteSize, pktFromQueue.data, pktFromQueue.size);
  757. aqBuffer->mPacketDescriptions[aqBuffer->mPacketDescriptionCount].mStartOffset = aqBuffer->mAudioDataByteSize;
  758. aqBuffer->mPacketDescriptions[aqBuffer->mPacketDescriptionCount].mDataByteSize = pktFromQueue.size;
  759. aqBuffer->mPacketDescriptions[aqBuffer->mPacketDescriptionCount].mVariableFramesInPacket = [_video audioCodecContext]->frame_size; // TODO: need to calculate it, 0 mean constant frame in packet
  760. aqBuffer->mPacketDescriptionCount++;
  761. aqBuffer->mAudioDataByteSize += pktFromQueue.size;
  762. }
  763. }
  764. //----------------------------------------------------------------
  765. #pragma mark - FFVideoScreenSource Protocol
  766. - (void) finishFrameForScreen: (FFVideoScreen*) screen
  767. {
  768. [_videoPicQueue popPictureWithBlockingMode:YES];
  769. }
  770. //----------------------------------------------------------------
  771. - (CGSize) videoFrameSize
  772. {
  773. if (!_video) {
  774. return CGSizeMake(0, 0);
  775. }
  776. return CGSizeMake([_video videoCodecContext]->width,
  777. [_video videoCodecContext]->height);
  778. }
  779. //----------------------------------------------------------------
  780. - (int) pixelFormat
  781. {
  782. return glPixelFormat;
  783. }
  784. //----------------------------------------------------------------
  785. /**
  786. This function called by Video screen object get the next video
  787. picture to display.
  788. @param screen screen that call this function
  789. @param lastPts last present time stamp (since start time) of last shown frame
  790. @return picture to render
  791. */
  792. -(const FFVideoPicture* const) getPictureForScreen: (FFVideoScreen*) screen
  793. screenClock:(NSTimeInterval)scrPts
  794. {
  795. // const FFVideoPicture* const picture = [_videoPicQueue pictureToReadWithBlock:NO];
  796. // double actual_delay, delay, sync_threshold;
  797. // delay = videoCurrentPts - videoFrameLastPts;
  798. // if (delay <=0 || delay >= 1) {
  799. // delay = videoFrameLastDelay;
  800. // }
  801. // videoFrameLastDelay = delay;
  802. double diff, ref_clock, aclk;
  803. const FFVideoPicture* picture = nil;
  804. ref_clock = [self masterClock];
  805. aclk = [self audioClock];
  806. //ref_clock = scrPts;
  807. for(;;){
  808. picture = [_videoPicQueue pictureToReadWithBlock:YES];
  809. if(_clockMode != FFDecodeMasterClockVideo ) {
  810. diff = [picture pts] - scrPts ;
  811. JLogDec(@"Delay: %f, rendering time: %f",diff, [screen renderingTime]);
  812. // JLogDec(@"video picture: pts: %f; ref_clk: %f; diff: %f, videoclk: %f, audioClk: %f, exClk: %f",
  813. // [picture pts],ref_clock,diff, [self videoClock],[self audioClock], [self externalClock]);
  814. JLogDec(@"vpts-aclk: %f, vpts-ref-clk: %f, refClk: %f, aclk: %f",[picture pts]-aclk, [picture pts] - ref_clock, ref_clock, aclk);
  815. // TEST, just break here, so video will ouput at max speed
  816. //JLog(@"Packet size %d, pic queue: %d", [_videoPktQueue count],[_videoPicQueue size]);
  817. //break;
  818. if (diff > AV_SYNC_VIDEO_THRESHOLD){
  819. usleep(diff* 1000000.0);
  820. break;
  821. }
  822. else if (diff < (-AV_SYNC_VIDEO_THRESHOLD))
  823. {
  824. if(![_videoPicQueue size])
  825. continue;
  826. break;
  827. }
  828. break;
  829. }
  830. }
  831. videoFrameLastPts = videoCurrentPts;
  832. videoCurrentPts = [picture pts];
  833. videoCurrentPtsTime = CACurrentMediaTime();
  834. return picture;
  835. }
  836. //----------------------------------------------------------------
  837. #pragma mark - FFAudioQueueSource Protocol
  838. /**
  839. There are two options for audio decoding: (1) using ffmpeg as external soft
  840. decoder, (2) using native ios decoder (nativ and soft).
  841. (1) If ffmpeg is used as decoder, AudioStreamBasicDescription (ASBD) should be
  842. formated as uncompressed LPCM format.
  843. (2) If ios decoder is used, ASBD should be formated to conform the codec of
  844. audio strem (often used: mp3, and aac)
  845. In this current version, we use ffmpeg as audio decoder, so ASBD is filled as
  846. uncompressed LPCM.
  847. */
  848. // TODO: Need improvment
  849. // Implement fillAudioStream for general case that includes iOS decoder (AAC, MP3).
  850. // Check output from ffmpeg for this value
  851. - (BOOL) fillAudioStreamDescription: (AudioStreamBasicDescription*) pASBD
  852. {
  853. if (!_video){
  854. JLogDec(@"Video has not loaded yet!");
  855. return FALSE;
  856. }
  857. if (decodeAudioMode == FFDecodeAudioModeFFmpeg) {
  858. /**
  859. Fill ASBD for LPCM case (ref: FillOutASBDForLPCM inline function in CoreAudioTypes
  860. */
  861. UInt32 validBitPerChannel = [FFMpegEngine bitsForSampleFormat: [_video audioCodecContext]->sample_fmt];
  862. UInt32 totalBitPerChannel = validBitPerChannel;
  863. BOOL isFloat = NO;
  864. BOOL isBigEndian = NO;
  865. BOOL isNonInterleaved = NO;
  866. UInt32 channelsPerFrame = [_video audioCodecContext]->channels;
  867. Float64 sampleRate = [_video audioCodecContext]->sample_rate;
  868. pASBD->mSampleRate = sampleRate;
  869. pASBD->mFormatID = kAudioFormatLinearPCM;
  870. pASBD->mFormatFlags =
  871. (isFloat ? kAudioFormatFlagIsFloat : kAudioFormatFlagIsSignedInteger) |
  872. (isBigEndian ? ((UInt32)kAudioFormatFlagIsBigEndian) : 0) |
  873. ((!isFloat && (validBitPerChannel == totalBitPerChannel)) ? kAudioFormatFlagIsPacked : kAudioFormatFlagIsAlignedHigh)|
  874. (isNonInterleaved ? ((UInt32)kAudioFormatFlagIsNonInterleaved) : 0);
  875. pASBD->mBytesPerPacket = (isNonInterleaved ? 1 : channelsPerFrame) * (totalBitPerChannel/8);
  876. pASBD->mFramesPerPacket = 1;
  877. pASBD->mBytesPerFrame = (isNonInterleaved ? 1 : channelsPerFrame) * (totalBitPerChannel/8);
  878. pASBD->mChannelsPerFrame = channelsPerFrame;
  879. pASBD->mBitsPerChannel = validBitPerChannel;
  880. pASBD->mReserved = 0;
  881. }else{ // decodeAudioMode == FFDecodeAudioNative
  882. pASBD->mSampleRate = [_video audioCodecContext]->sample_rate;
  883. pASBD->mFormatID = kAudioFormatMPEG4AAC;
  884. pASBD->mFormatFlags = kMPEG4Object_AAC_Main;
  885. // It's VBR, dont need to set these value
  886. pASBD->mBytesPerPacket = 0;
  887. pASBD->mFramesPerPacket = [_video audioCodecContext]->frame_size;
  888. pASBD->mBitsPerChannel = [FFMpegEngine bitsForSampleFormat: [_video audioCodecContext]->sample_fmt];
  889. pASBD->mChannelsPerFrame = [_video audioCodecContext]->channels;
  890. //pASBD->mBytesPerFrame = pASBD->mChannelsPerFrame * pASBD->mBitsPerChannel / 8;
  891. pASBD->mBytesPerFrame = 0;
  892. }
  893. return TRUE;
  894. }
  895. //----------------------------------------------------------------
  896. /**
  897. In case of LCPM, p1 packet contain 1 frame so maximum packet size is size of
  898. one frame.
  899. */
  900. // TODO: Need improvment
  901. // - Implement fillAudioStream for general case that includes iOS decoder (AAC, MP3).
  902. // - Check output from ffmpeg for interleave value
  903. - (UInt32) maxAudioPacketSize
  904. {
  905. if (decodeAudioMode == FFDecodeAudioModeFFmpeg) {
  906. UInt32 channelsPerFrame = [_video audioCodecContext]->channels;
  907. BOOL isNonInterleaved = NO;
  908. UInt32 totalBitPerChannel = [FFMpegEngine bitsForSampleFormat: [_video audioCodecContext]->sample_fmt];
  909. return (isNonInterleaved ? 1 : channelsPerFrame) * (totalBitPerChannel/8);
  910. }else{
  911. return [_video audioCodecContext]->frame_size;
  912. //return 300;
  913. }
  914. }
  915. //----------------------------------------------------------------
  916. /**
  917. Render audio buffer with output data from decoder
  918. @param aqBuffer the buffer that decode need to fill audio samples in
  919. @param pts the time reference, indicate what set of sample should be filled in
  920. */
  921. // TODO: Implement for both ffmpeg-decoder and iOS decoder
  922. //#define USE_AUDIO_THREAD
  923. - (void) renderAudioBuffer:(AudioQueueBufferRef) aqBuffer
  924. forPts:(NSTimeInterval)pts
  925. {
  926. //JLog(@"Rendering AQ buffer");
  927. if (decodeAudioMode == FFDecodeAudioModeFFmpeg) {
  928. /*
  929. // Generate sine noise sound for test
  930. double amplitude = 0.25 * 0x3FFF;
  931. for (int n = 0; n < aqBuffer->mAudioDataBytesCapacity; n+=2)
  932. {
  933. SInt16* pSample = (aqBuffer->mAudioData + n);
  934. *pSample = (short)(amplitude * ((double)rand()/(double)(RAND_MAX - 1)));
  935. }
  936. aqBuffer->mAudioDataByteSize = aqBuffer->mAudioDataBytesCapacity;
  937. //*/
  938. #ifdef USE_AUDIO_THREAD
  939. NSTimeInterval bufferPts;
  940. int readBytes = [_audioBuffer popSampleTo:aqBuffer->mAudioData
  941. size:aqBuffer->mAudioDataBytesCapacity
  942. outPts:&bufferPts
  943. blocked:YES];
  944. aqBuffer->mAudioDataByteSize = readBytes;
  945. JLogDec(@"Fill audio buffer");
  946. #else
  947. [self fillPCMAudioIntoBuff:aqBuffer->mAudioData
  948. capacity:aqBuffer->mAudioDataBytesCapacity];
  949. aqBuffer->mAudioDataByteSize = aqBuffer->mAudioDataBytesCapacity;
  950. #endif
  951. }else{// decodeAudioMode == FFDecodeAudioNative
  952. // TODO: Implementation
  953. [self fillAudioPktToBuff: aqBuffer forPts: (NSTimeInterval) pts];
  954. }
  955. }
  956. - (int) sampleRate
  957. {
  958. return [_video audioCodecContext]->sample_rate;
  959. }
  960. @end
  961. //----------------------------------------------------------------
  962. #pragma mark - FFDecoder's Video Properties
  963. @implementation FFDecoder (VideoProperties)
  964. @dynamic mediaSourceType;
  965. - (int) mediaSourceType
  966. {
  967. return 0;
  968. }
  969. - (void) setMediaSourceType:(int)mediaSourceType
  970. {
  971. }
  972. - (double) currentPlaybackTime
  973. {
  974. return 0;
  975. }
  976. - (float) currentPlaybackRate
  977. {
  978. return 0;
  979. }
  980. - (int) mediaTypes
  981. {
  982. return 0;
  983. }
  984. - (float) duration
  985. {
  986. return 0;
  987. }
  988. - (float) playableDuration
  989. {
  990. return 0;
  991. }
  992. // CGSizeZero if not known/applicable.
  993. - (CGSize) videoSize
  994. {
  995. return CGSizeMake(0, 0);
  996. }
  997. // return NaN indicates the natural start time
  998. - (float) startTime
  999. {
  1000. return NAN;
  1001. }
  1002. // return NaN indicates the natural end time
  1003. - (float) endTime
  1004. {
  1005. return NAN;
  1006. }
  1007. @end