@ -20,15 +20,16 @@
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# include <pthread.h>
# include <CoreFoundation/CFDictionary.h>
# include <CoreFoundation/CFNumber.h>
# include <CoreFoundation/CFData.h>
# include <CoreFoundation/CFString.h>
# include "libavutil/avutil.h"
# include "vda_internal.h"
# if FF_API_VDA_ASYNC
# include <CoreFoundation/CFString.h>
/* Helper to create a dictionary according to the given pts. */
static CFDictionaryRef vda_dictionary_with_pts ( int64_t i_pts )
{
@ -76,7 +77,7 @@ static void vda_clear_queue(struct vda_context *vda_ctx)
pthread_mutex_unlock ( & vda_ctx - > queue_mutex ) ;
}
# endif
/* Decoder callback that adds the vda frame to the queue in display order. */
static void vda_decoder_callback ( void * vda_hw_ctx ,
@ -86,8 +87,6 @@ static void vda_decoder_callback (void *vda_hw_ctx,
CVImageBufferRef image_buffer )
{
struct vda_context * vda_ctx = ( struct vda_context * ) vda_hw_ctx ;
vda_frame * new_frame ;
vda_frame * queue_walker ;
if ( ! image_buffer )
return ;
@ -95,46 +94,54 @@ static void vda_decoder_callback (void *vda_hw_ctx,
if ( vda_ctx - > cv_pix_fmt_type ! = CVPixelBufferGetPixelFormatType ( image_buffer ) )
return ;
new_frame = av_mallocz ( sizeof ( vda_frame ) ) ;
if ( ! new_frame )
return ;
new_frame - > next_frame = NULL ;
new_frame - > cv_buffer = CVPixelBufferRetain ( image_buffer ) ;
new_frame - > pts = vda_pts_from_dictionary ( user_info ) ;
pthread_mutex_lock ( & vda_ctx - > queue_mutex ) ;
queue_walker = vda_ctx - > queue ;
if ( ! queue_walker | | ( new_frame - > pts < queue_walker - > pts ) ) {
/* we have an empty queue, or this frame earlier than the current queue head */
new_frame - > next_frame = queue_walker ;
vda_ctx - > queue = new_frame ;
} else {
/* walk the queue and insert this frame where it belongs in display order */
vda_frame * next_frame ;
while ( 1 ) {
next_frame = queue_walker - > next_frame ;
if ( ! next_frame | | ( new_frame - > pts < next_frame - > pts ) ) {
new_frame - > next_frame = next_frame ;
queue_walker - > next_frame = new_frame ;
break ;
if ( vda_ctx - > use_sync_decoding ) {
vda_ctx - > cv_buffer = CVPixelBufferRetain ( image_buffer ) ;
}
else {
vda_frame * new_frame ;
vda_frame * queue_walker ;
new_frame = av_mallocz ( sizeof ( vda_frame ) ) ;
if ( ! new_frame )
return ;
new_frame - > next_frame = NULL ;
new_frame - > cv_buffer = CVPixelBufferRetain ( image_buffer ) ;
new_frame - > pts = vda_pts_from_dictionary ( user_info ) ;
pthread_mutex_lock ( & vda_ctx - > queue_mutex ) ;
queue_walker = vda_ctx - > queue ;
if ( ! queue_walker | | ( new_frame - > pts < queue_walker - > pts ) ) {
/* we have an empty queue, or this frame earlier than the current queue head */
new_frame - > next_frame = queue_walker ;
vda_ctx - > queue = new_frame ;
} else {
/* walk the queue and insert this frame where it belongs in display order */
vda_frame * next_frame ;
while ( 1 ) {
next_frame = queue_walker - > next_frame ;
if ( ! next_frame | | ( new_frame - > pts < next_frame - > pts ) ) {
new_frame - > next_frame = next_frame ;
queue_walker - > next_frame = new_frame ;
break ;
}
queue_walker = next_frame ;
}
queue_walker = next_frame ;
}
}
pthread_mutex_unlock ( & vda_ctx - > queue_mutex ) ;
pthread_mutex_unlock ( & vda_ctx - > queue_mutex ) ;
}
}
int ff_vda_create_decoder ( struct vda_context * vda_ctx ,
uint8_t * extradata ,
int extradata_size )
{
OSStatus status = kVDADecoderNoErr ;
OSStatus status ;
CFNumberRef height ;
CFNumberRef width ;
CFNumberRef format ;
@ -147,7 +154,9 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx,
vda_ctx - > bitstream = NULL ;
vda_ctx - > ref_size = 0 ;
# if FF_API_VDA_ASYNC
pthread_mutex_init ( & vda_ctx - > queue_mutex , NULL ) ;
# endif
/* Each VCL NAL in the bistream sent to the decoder
* is preceded by a 4 bytes length header .
@ -216,10 +225,7 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx,
CFRelease ( cv_pix_fmt ) ;
CFRelease ( buffer_attributes ) ;
if ( kVDADecoderNoErr ! = status )
return status ;
return 0 ;
return status ;
}
int ff_vda_destroy_decoder ( struct vda_context * vda_ctx )
@ -229,19 +235,17 @@ int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
if ( vda_ctx - > decoder )
status = VDADecoderDestroy ( vda_ctx - > decoder ) ;
# if FF_API_VDA_ASYNC
vda_clear_queue ( vda_ctx ) ;
pthread_mutex_destroy ( & vda_ctx - > queue_mutex ) ;
# endif
if ( vda_ctx - > bitstream )
av_freep ( & vda_ctx - > bitstream ) ;
if ( kVDADecoderNoErr ! = status )
return status ;
return 0 ;
return status ;
}
# if FF_API_VDA_ASYNC
vda_frame * ff_vda_queue_pop ( struct vda_context * vda_ctx )
{
vda_frame * top_frame ;
@ -270,7 +274,7 @@ int ff_vda_decoder_decode(struct vda_context *vda_ctx,
int bitstream_size ,
int64_t frame_pts )
{
OSStatus status = kVDADecoderNoErr ;
OSStatus status ;
CFDictionaryRef user_info ;
CFDataRef coded_frame ;
@ -282,8 +286,26 @@ int ff_vda_decoder_decode(struct vda_context *vda_ctx,
CFRelease ( user_info ) ;
CFRelease ( coded_frame ) ;
if ( kVDADecoderNoErr ! = status )
return status ;
return status ;
}
# endif
int ff_vda_sync_decode ( struct vda_context * vda_ctx )
{
OSStatus status ;
CFDataRef coded_frame ;
uint32_t flush_flags = 1 < < 0 ; ///< kVDADecoderFlush_emitFrames
coded_frame = CFDataCreate ( kCFAllocatorDefault ,
vda_ctx - > bitstream ,
vda_ctx - > bitstream_size ) ;
status = VDADecoderDecode ( vda_ctx - > decoder , 0 , coded_frame , NULL ) ;
if ( kVDADecoderNoErr = = status )
status = VDADecoderFlush ( vda_ctx - > decoder , flush_flags ) ;
CFRelease ( coded_frame ) ;
return 0 ;
return status ;
}