00001
00002
00003
00004 #include "mythlogging.h"
00005 #define LOC QString("VDADec: ")
00006 #define ERR QString("VDADec error: ")
00007
00008 #include "frame.h"
00009 #include "myth_imgconvert.h"
00010 #include "util-osx-cocoa.h"
00011 #include "privatedecoder_vda.h"
00012 #ifdef USING_QUARTZ_VIDEO
00013 #undef CodecType
00014 #import "QuickTime/ImageCompression.h"
00015 #endif
00016 #include "H264Parser.h"
00017
00018 extern "C" {
00019 #include "libavformat/avformat.h"
00020 }
00021 VDALibrary *gVDALib = NULL;
00022
00023 VDALibrary* VDALibrary::GetVDALibrary(void)
00024 {
00025 static QMutex vda_create_lock;
00026 QMutexLocker locker(&vda_create_lock);
00027 if (gVDALib)
00028 return gVDALib;
00029 gVDALib = new VDALibrary();
00030 if (gVDALib)
00031 {
00032 if (gVDALib->IsValid())
00033 return gVDALib;
00034 delete gVDALib;
00035 }
00036 gVDALib = NULL;
00037 return gVDALib;
00038 }
00039
00040 VDALibrary::VDALibrary(void)
00041 : decoderCreate(NULL), decoderDecode(NULL), decoderFlush(NULL),
00042 decoderDestroy(NULL), decoderConfigWidth(NULL),
00043 decoderConfigHeight(NULL), decoderConfigSourceFmt(NULL),
00044 decoderConfigAVCCData(NULL), m_lib(NULL), m_valid(false)
00045 {
00046 m_lib = new QLibrary(VDA_DECODER_PATH);
00047 if (m_lib)
00048 {
00049 decoderCreate = (MYTH_VDADECODERCREATE)
00050 m_lib->resolve("VDADecoderCreate");
00051 decoderDecode = (MYTH_VDADECODERDECODE)
00052 m_lib->resolve("VDADecoderDecode");
00053 decoderFlush = (MYTH_VDADECODERFLUSH)
00054 m_lib->resolve("VDADecoderFlush");
00055 decoderDestroy = (MYTH_VDADECODERDESTROY)
00056 m_lib->resolve("VDADecoderDestroy");
00057 decoderConfigWidth = (CFStringRef*)
00058 m_lib->resolve("kVDADecoderConfiguration_Width");
00059 decoderConfigHeight = (CFStringRef*)
00060 m_lib->resolve("kVDADecoderConfiguration_Height");
00061 decoderConfigSourceFmt = (CFStringRef*)
00062 m_lib->resolve("kVDADecoderConfiguration_SourceFormat");
00063 decoderConfigAVCCData = (CFStringRef*)
00064 m_lib->resolve("kVDADecoderConfiguration_avcCData");
00065 }
00066
00067 if (decoderCreate && decoderDecode && decoderFlush && decoderDestroy &&
00068 decoderConfigHeight && decoderConfigWidth && decoderConfigSourceFmt &&
00069 decoderConfigAVCCData && m_lib->isLoaded())
00070 {
00071 m_valid = true;
00072 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00073 "Loaded VideoDecodeAcceleration library.");
00074 }
00075 else
00076 LOG(VB_GENERAL, LOG_ERR, LOC +
00077 "Failed to load VideoDecodeAcceleration library.");
00078 }
00079
00080 #define INIT_ST OSStatus vda_st; bool ok = true
00081 #define CHECK_ST \
00082 ok &= (vda_st == kVDADecoderNoErr); \
00083 if (!ok) \
00084 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error at %1:%2 (#%3, %4)") \
00085 .arg(__FILE__).arg( __LINE__).arg(vda_st) \
00086 .arg(vda_err_to_string(vda_st)))
00087
00088 QString vda_err_to_string(OSStatus err)
00089 {
00090 switch (err)
00091 {
00092 case kVDADecoderHardwareNotSupportedErr:
00093 return "Hardware not supported";
00094 case kVDADecoderFormatNotSupportedErr:
00095 return "Format not supported";
00096 case kVDADecoderConfigurationError:
00097 return "Configuration error";
00098 case kVDADecoderDecoderFailedErr:
00099 return "Decoder failed";
00100 case paramErr:
00101 return "Parameter error";
00102 }
00103 return "Unknown error";
00104 }
00105
00107
00108
00109
00110
00111
00112
00113
00114 #define VDA_RB16(x) \
00115 ((((const uint8_t*)(x))[0] << 8) | \
00116 ((const uint8_t*)(x)) [1])
00117
00118 #define VDA_RB24(x) \
00119 ((((const uint8_t*)(x))[0] << 16) | \
00120 (((const uint8_t*)(x))[1] << 8) | \
00121 ((const uint8_t*)(x))[2])
00122
00123 #define VDA_RB32(x) \
00124 ((((const uint8_t*)(x))[0] << 24) | \
00125 (((const uint8_t*)(x))[1] << 16) | \
00126 (((const uint8_t*)(x))[2] << 8) | \
00127 ((const uint8_t*)(x))[3])
00128
00129 #define VDA_WB32(p, d) { \
00130 ((uint8_t*)(p))[3] = (d); \
00131 ((uint8_t*)(p))[2] = (d) >> 8; \
00132 ((uint8_t*)(p))[1] = (d) >> 16; \
00133 ((uint8_t*)(p))[0] = (d) >> 24; }
00134
00135 static const uint8_t *avc_find_startcode_internal(const uint8_t *p, const uint8_t *end)
00136 {
00137 const uint8_t *a = p + 4 - ((intptr_t)p & 3);
00138
00139 for (end -= 3; p < a && p < end; p++)
00140 {
00141 if (p[0] == 0 && p[1] == 0 && p[2] == 1)
00142 return p;
00143 }
00144
00145 for (end -= 3; p < end; p += 4)
00146 {
00147 uint32_t x = *(const uint32_t*)p;
00148 if ((x - 0x01010101) & (~x) & 0x80808080)
00149 {
00150 if (p[1] == 0)
00151 {
00152 if (p[0] == 0 && p[2] == 1)
00153 return p;
00154 if (p[2] == 0 && p[3] == 1)
00155 return p+1;
00156 }
00157 if (p[3] == 0)
00158 {
00159 if (p[2] == 0 && p[4] == 1)
00160 return p+2;
00161 if (p[4] == 0 && p[5] == 1)
00162 return p+3;
00163 }
00164 }
00165 }
00166
00167 for (end += 3; p < end; p++)
00168 {
00169 if (p[0] == 0 && p[1] == 0 && p[2] == 1)
00170 return p;
00171 }
00172
00173 return end + 3;
00174 }
00175
00176 const uint8_t *avc_find_startcode(const uint8_t *p, const uint8_t *end)
00177 {
00178 const uint8_t *out= avc_find_startcode_internal(p, end);
00179 if (p<out && out<end && !out[-1])
00180 out--;
00181 return out;
00182 }
00183
00184 const int avc_parse_nal_units(AVIOContext *pb, const uint8_t *buf_in, int size)
00185 {
00186 const uint8_t *p = buf_in;
00187 const uint8_t *end = p + size;
00188 const uint8_t *nal_start, *nal_end;
00189
00190 size = 0;
00191 nal_start = avc_find_startcode(p, end);
00192 while (nal_start < end)
00193 {
00194 while (!*(nal_start++));
00195 nal_end = avc_find_startcode(nal_start, end);
00196 avio_wb32(pb, nal_end - nal_start);
00197 avio_write(pb, nal_start, nal_end - nal_start);
00198 size += 4 + nal_end - nal_start;
00199 nal_start = nal_end;
00200 }
00201 return size;
00202 }
00203
00204 const int avc_parse_nal_units_buf(const uint8_t *buf_in,
00205 uint8_t **buf, int *size)
00206 {
00207 AVIOContext *pb;
00208 int ret = avio_open_dyn_buf(&pb);
00209 if (ret < 0)
00210 return ret;
00211
00212 avc_parse_nal_units(pb, buf_in, *size);
00213
00214 av_freep(buf);
00215 *size = avio_close_dyn_buf(pb, buf);
00216 return 0;
00217 }
00218
00219 const int isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
00220 {
00221
00222 if (len > 6)
00223 {
00224
00225 if (VDA_RB32(data) == 0x00000001 || VDA_RB24(data) == 0x000001)
00226 {
00227 uint8_t *buf=NULL, *end, *start;
00228 uint32_t sps_size=0, pps_size=0;
00229 uint8_t *sps=0, *pps=0;
00230
00231 int ret = avc_parse_nal_units_buf(data, &buf, &len);
00232 if (ret < 0)
00233 return ret;
00234 start = buf;
00235 end = buf + len;
00236
00237
00238 while (buf < end)
00239 {
00240 unsigned int size;
00241 uint8_t nal_type;
00242 size = VDA_RB32(buf);
00243 nal_type = buf[4] & 0x1f;
00244 if (nal_type == 7)
00245 {
00246 sps = buf + 4;
00247 sps_size = size;
00248
00249
00250 }
00251 else if (nal_type == 8)
00252 {
00253 pps = buf + 4;
00254 pps_size = size;
00255 }
00256 buf += size + 4;
00257 }
00258 if (!sps)
00259 {
00260 LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid data (sps)");
00261 return -1;
00262 }
00263
00264 avio_w8(pb, 1);
00265 avio_w8(pb, sps[1]);
00266 avio_w8(pb, sps[2]);
00267 avio_w8(pb, sps[3]);
00268 avio_w8(pb, 0xff);
00269 avio_w8(pb, 0xe1);
00270
00271 avio_wb16(pb, sps_size);
00272 avio_write(pb, sps, sps_size);
00273 if (pps)
00274 {
00275 avio_w8(pb, 1);
00276 avio_wb16(pb, pps_size);
00277 avio_write(pb, pps, pps_size);
00278 }
00279 av_free(start);
00280 }
00281 else
00282 {
00283 avio_write(pb, data, len);
00284 }
00285 }
00286 return 0;
00287 }
00288
00289 void PrivateDecoderVDA::GetDecoders(render_opts &opts)
00290 {
00291 opts.decoders->append("vda");
00292 (*opts.equiv_decoders)["vda"].append("nuppel");
00293 (*opts.equiv_decoders)["vda"].append("ffmpeg");
00294 (*opts.equiv_decoders)["vda"].append("dummy");
00295 }
00296
00297 PrivateDecoderVDA::PrivateDecoderVDA()
00298 : PrivateDecoder(), m_lib(NULL), m_decoder(NULL), m_size(QSize()),
00299 m_frame_lock(QMutex::Recursive), m_frames_decoded(0), m_annexb(false),
00300 m_slice_count(0), m_convert_3byteTo4byteNALSize(false), m_max_ref_frames(0)
00301 {
00302 }
00303
00304 PrivateDecoderVDA::~PrivateDecoderVDA()
00305 {
00306 Reset();
00307 if (m_decoder)
00308 {
00309 INIT_ST;
00310 vda_st = m_lib->decoderDestroy((VDADecoder)m_decoder);
00311 CHECK_ST;
00312 }
00313 m_decoder = NULL;
00314 }
00315
00316 bool PrivateDecoderVDA::Init(const QString &decoder,
00317 PlayerFlags flags,
00318 AVCodecContext *avctx)
00319 {
00320 if ((decoder != "vda") || (avctx->codec_id != CODEC_ID_H264) ||
00321 !(flags & kDecodeAllowEXT) || !avctx)
00322 return false;
00323
00324 m_lib = VDALibrary::GetVDALibrary();
00325 if (!m_lib)
00326 return false;
00327
00328 uint8_t *extradata = avctx->extradata;
00329 int extrasize = avctx->extradata_size;
00330 if (!extradata || extrasize < 7)
00331 return false;
00332
00333 CFDataRef avc_cdata = NULL;
00334 if (extradata[0] != 1)
00335 {
00336 if (extradata[0] == 0 && extradata[1] == 0 && extradata[2] == 0 &&
00337 extradata[3] == 1)
00338 {
00339
00340
00341 AVIOContext *pb;
00342 if (avio_open_dyn_buf(&pb) < 0)
00343 {
00344 return false;
00345 }
00346
00347 m_annexb = true;
00348 isom_write_avcc(pb, extradata, extrasize);
00349
00350 extradata = NULL;
00351
00352 extrasize = avio_close_dyn_buf(pb, &extradata);
00353
00354 avc_cdata = CFDataCreate(kCFAllocatorDefault,
00355 (const uint8_t*)extradata, extrasize);
00356
00357 av_free(extradata);
00358 }
00359 else
00360 {
00361 LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid avcC atom data");
00362 return false;
00363 }
00364 }
00365 else
00366 {
00367 if (extradata[4] == 0xFE)
00368 {
00369
00370
00371 extradata[4] = 0xFF;
00372 m_convert_3byteTo4byteNALSize = true;
00373 }
00374
00375 avc_cdata = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)extradata,
00376 extrasize);
00377 }
00378
00379 OSType format = 'avc1';
00380
00381
00382
00383 uint32_t avcc_len = CFDataGetLength(avc_cdata);
00384 if (avcc_len < 8)
00385 {
00386
00387 CFRelease(avc_cdata);
00388 return false;
00389 }
00390 bool interlaced = false;
00391 uint8_t *spc = (uint8_t*)CFDataGetBytePtr(avc_cdata) + 6;
00392 uint32_t sps_size = VDA_RB16(spc);
00393 if (sps_size)
00394 {
00395 H264Parser *h264_parser = new H264Parser();
00396 h264_parser->parse_SPS(spc+3, sps_size-1,
00397 interlaced, m_max_ref_frames);
00398 delete h264_parser;
00399 }
00400 else
00401 {
00402 m_max_ref_frames = avctx->refs;
00403 }
00404 if (interlaced)
00405 {
00406 LOG(VB_GENERAL, LOG_ERR, LOC + "Possible interlaced content. Aborting");
00407 CFRelease(avc_cdata);
00408 return false;
00409 }
00410 if (m_max_ref_frames == 0)
00411 {
00412 m_max_ref_frames = 2;
00413 }
00414
00415 if (avctx->profile == FF_PROFILE_H264_MAIN && avctx->level == 32 &&
00416 m_max_ref_frames > 4)
00417 {
00418
00419 LOG(VB_GENERAL, LOG_ERR,
00420 LOC + "Main@L3.2 detected, VDA cannot decode.");
00421 CFRelease(avc_cdata);
00422 return false;
00423 }
00424
00425 int32_t width = avctx->coded_width;
00426 int32_t height = avctx->coded_height;
00427 m_size = QSize(width, height);
00428 m_slice_count = avctx->slice_count;
00429
00430 int mbs = ceil((double)width / 16.0f);
00431 if (((mbs == 49) || (mbs == 54 ) || (mbs == 59 ) || (mbs == 64) ||
00432 (mbs == 113) || (mbs == 118) || (mbs == 123) || (mbs == 128)))
00433 {
00434 LOG(VB_PLAYBACK, LOG_WARNING, LOC +
00435 QString("Warning: VDA decoding may not be supported for this "
00436 "video stream (width %1)").arg(width));
00437 }
00438
00439 CFMutableDictionaryRef destinationImageBufferAttributes =
00440 CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
00441 &kCFTypeDictionaryKeyCallBacks,
00442 &kCFTypeDictionaryValueCallBacks);
00443 #ifdef USING_QUARTZ_VIDEO
00444 OSType cvPixelFormatType = k422YpCbCr8PixelFormat;
00445 #else
00446 OSType cvPixelFormatType = kCVPixelFormatType_422YpCbCr8;
00447 #endif
00448 CFNumberRef pixelFormat = CFNumberCreate(kCFAllocatorDefault,
00449 kCFNumberSInt32Type,
00450 &cvPixelFormatType);
00451 CFDictionarySetValue(destinationImageBufferAttributes,
00452 kCVPixelBufferPixelFormatTypeKey,
00453 pixelFormat);
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 CFMutableDictionaryRef decoderConfig =
00464 CFDictionaryCreateMutable(
00465 kCFAllocatorDefault, 4,
00466 &kCFTypeDictionaryKeyCallBacks,
00467 &kCFTypeDictionaryValueCallBacks);
00468 CFNumberRef avc_width = CFNumberCreate(kCFAllocatorDefault,
00469 kCFNumberSInt32Type, &width);
00470 CFNumberRef avc_height = CFNumberCreate(kCFAllocatorDefault,
00471 kCFNumberSInt32Type, &height);
00472 CFNumberRef avc_format = CFNumberCreate(kCFAllocatorDefault,
00473 kCFNumberSInt32Type, &format);
00474
00475 CFDictionarySetValue(decoderConfig, *m_lib->decoderConfigHeight, avc_height);
00476 CFDictionarySetValue(decoderConfig, *m_lib->decoderConfigWidth, avc_width);
00477 CFDictionarySetValue(decoderConfig, *m_lib->decoderConfigSourceFmt, avc_format);
00478 CFDictionarySetValue(decoderConfig, *m_lib->decoderConfigAVCCData, avc_cdata);
00479 CFRelease(avc_width);
00480 CFRelease(avc_height);
00481 CFRelease(avc_format);
00482 CFRelease(avc_cdata);
00483
00484 INIT_ST;
00485 vda_st = m_lib->decoderCreate(decoderConfig, destinationImageBufferAttributes,
00486 (VDADecoderOutputCallback*)VDADecoderCallback,
00487 this, (VDADecoder*)&m_decoder);
00488 CHECK_ST;
00489 CFRelease(decoderConfig);
00490 CFRelease(destinationImageBufferAttributes);
00491
00492 if (ok)
00493 {
00494 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00495 QString("Created VDA decoder: Size %1x%2 Ref Frames %3 "
00496 "Slices %5 AnnexB %6")
00497 .arg(width).arg(height).arg(m_max_ref_frames)
00498 .arg(m_slice_count).arg(m_annexb ? "Yes" : "No"));
00499 }
00500 m_max_ref_frames = std::min(m_max_ref_frames, 5);
00501 return ok;
00502 }
00503
00504 bool PrivateDecoderVDA::Reset(void)
00505 {
00506 if (m_lib && m_decoder)
00507 m_lib->decoderFlush((VDADecoder)m_decoder, 0 );
00508
00509 m_frames_decoded = 0;
00510 m_frame_lock.lock();
00511 while (!m_decoded_frames.empty())
00512 PopDecodedFrame();
00513 m_frame_lock.unlock();
00514 return true;
00515 }
00516
00517 void PrivateDecoderVDA::PopDecodedFrame(void)
00518 {
00519 QMutexLocker lock(&m_frame_lock);
00520 if (m_decoded_frames.isEmpty())
00521 return;
00522 CVPixelBufferRelease(m_decoded_frames.last().buffer);
00523 m_decoded_frames.removeLast();
00524 }
00525
00526 bool PrivateDecoderVDA::HasBufferedFrames(void)
00527 {
00528 m_frame_lock.lock();
00529 bool result = m_decoded_frames.size() > 0;
00530 m_frame_lock.unlock();
00531 return result;
00532 }
00533
00534 int PrivateDecoderVDA::GetFrame(AVStream *stream,
00535 AVFrame *picture,
00536 int *got_picture_ptr,
00537 AVPacket *pkt)
00538 {
00539 if (!pkt)
00540
00541 CocoaAutoReleasePool pool;
00542 int result = -1;
00543 if (!m_lib || !stream)
00544 return result;
00545
00546 AVCodecContext *avctx = stream->codec;
00547 if (!avctx)
00548 return result;
00549
00550 if (pkt)
00551 {
00552 CFDataRef avc_demux;
00553 CFDictionaryRef params;
00554 if (m_annexb)
00555 {
00556
00557 AVIOContext *pb;
00558 int demuxer_bytes;
00559 uint8_t *demuxer_content;
00560
00561 if(avio_open_dyn_buf(&pb) < 0)
00562 {
00563 return result;
00564 }
00565 demuxer_bytes = avc_parse_nal_units(pb, pkt->data, pkt->size);
00566 demuxer_bytes = avio_close_dyn_buf(pb, &demuxer_content);
00567 avc_demux = CFDataCreate(kCFAllocatorDefault, demuxer_content, demuxer_bytes);
00568 av_free(demuxer_content);
00569 }
00570 else if (m_convert_3byteTo4byteNALSize)
00571 {
00572
00573 AVIOContext *pb;
00574 if (avio_open_dyn_buf(&pb) < 0)
00575 {
00576 return result;
00577 }
00578
00579 uint32_t nal_size;
00580 uint8_t *end = pkt->data + pkt->size;
00581 uint8_t *nal_start = pkt->data;
00582 while (nal_start < end)
00583 {
00584 nal_size = VDA_RB24(nal_start);
00585 avio_wb32(pb, nal_size);
00586 nal_start += 3;
00587 avio_write(pb, nal_start, nal_size);
00588 nal_start += nal_size;
00589 }
00590
00591 uint8_t *demuxer_content;
00592 int demuxer_bytes = avio_close_dyn_buf(pb, &demuxer_content);
00593 avc_demux = CFDataCreate(kCFAllocatorDefault, demuxer_content, demuxer_bytes);
00594 av_free(demuxer_content);
00595 }
00596 else
00597 {
00598 avc_demux = CFDataCreate(kCFAllocatorDefault, pkt->data, pkt->size);
00599 }
00600
00601 CFStringRef keys[4] = { CFSTR("FRAME_PTS"),
00602 CFSTR("FRAME_INTERLACED"), CFSTR("FRAME_TFF"),
00603 CFSTR("FRAME_REPEAT") };
00604 CFNumberRef values[5];
00605 values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type,
00606 &pkt->pts);
00607 values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type,
00608 &picture->interlaced_frame);
00609 values[2] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type,
00610 &picture->top_field_first);
00611 values[3] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type,
00612 &picture->repeat_pict);
00613 params = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&keys,
00614 (const void **)&values, 4,
00615 &kCFTypeDictionaryKeyCallBacks,
00616 &kCFTypeDictionaryValueCallBacks);
00617
00618 INIT_ST;
00619 vda_st = m_lib->decoderDecode((VDADecoder)m_decoder, 0, avc_demux, params);
00620 CHECK_ST;
00621 if (vda_st == kVDADecoderNoErr)
00622 result = pkt->size;
00623 CFRelease(avc_demux);
00624 CFRelease(params);
00625 }
00626
00627 if (m_decoded_frames.size() < m_max_ref_frames)
00628 return result;
00629
00630 *got_picture_ptr = 1;
00631 m_frame_lock.lock();
00632 VDAFrame vdaframe = m_decoded_frames.takeLast();
00633 m_frame_lock.unlock();
00634
00635 if (avctx->get_buffer(avctx, picture) < 0)
00636 return -1;
00637
00638 picture->reordered_opaque = vdaframe.pts;
00639 picture->interlaced_frame = vdaframe.interlaced_frame;
00640 picture->top_field_first = vdaframe.top_field_first;
00641 picture->repeat_pict = vdaframe.repeat_pict;
00642 VideoFrame *frame = (VideoFrame*)picture->opaque;
00643
00644 PixelFormat in_fmt = PIX_FMT_NONE;
00645 PixelFormat out_fmt = PIX_FMT_NONE;
00646 if (vdaframe.format == 'BGRA')
00647 in_fmt = PIX_FMT_BGRA;
00648 else if (vdaframe.format == '2vuy')
00649 in_fmt = PIX_FMT_UYVY422;
00650
00651 if (frame->codec == FMT_YV12)
00652 out_fmt = PIX_FMT_YUV420P;
00653
00654 if (out_fmt != PIX_FMT_NONE && in_fmt != PIX_FMT_NONE && frame->buf)
00655 {
00656 CVPixelBufferLockBaseAddress(vdaframe.buffer, 0);
00657 uint8_t* base = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(vdaframe.buffer, 0);
00658 AVPicture img_in, img_out;
00659 avpicture_fill(&img_out, (uint8_t *)frame->buf, out_fmt,
00660 frame->width, frame->height);
00661 avpicture_fill(&img_in, base, in_fmt,
00662 frame->width, frame->height);
00663 myth_sws_img_convert(&img_out, out_fmt, &img_in, in_fmt,
00664 frame->width, frame->height);
00665 CVPixelBufferUnlockBaseAddress(vdaframe.buffer, 0);
00666 }
00667 else
00668 {
00669 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to convert decoded frame.");
00670 }
00671
00672 CVPixelBufferRelease(vdaframe.buffer);
00673 return result;
00674 }
00675
00676 void PrivateDecoderVDA::VDADecoderCallback(void *decompressionOutputRefCon,
00677 CFDictionaryRef frameInfo,
00678 OSStatus status,
00679 uint32_t infoFlags,
00680 CVImageBufferRef imageBuffer)
00681 {
00682 CocoaAutoReleasePool pool;
00683 PrivateDecoderVDA *decoder = (PrivateDecoderVDA*)decompressionOutputRefCon;
00684
00685 if (kVDADecodeInfo_FrameDropped & infoFlags)
00686 {
00687 LOG(VB_GENERAL, LOG_ERR, LOC + "Callback: Decoder dropped frame");
00688 return;
00689 }
00690
00691 if (!imageBuffer)
00692 {
00693 LOG(VB_GENERAL, LOG_ERR, LOC +
00694 "Callback: decoder returned empty buffer.");
00695 return;
00696 }
00697
00698 INIT_ST;
00699 vda_st = status;
00700 CHECK_ST;
00701
00702 OSType format_type = CVPixelBufferGetPixelFormatType(imageBuffer);
00703 if ((format_type != '2vuy') && (format_type != 'BGRA'))
00704 {
00705 LOG(VB_GENERAL, LOG_ERR, LOC +
00706 QString("Callback: image buffer format unknown (%1)")
00707 .arg(format_type));
00708 return;
00709 }
00710
00711 int64_t pts = AV_NOPTS_VALUE;
00712 int8_t interlaced = 0;
00713 int8_t topfirst = 0;
00714 int8_t repeatpic = 0;
00715 CFNumberRef ptsref = (CFNumberRef)CFDictionaryGetValue(frameInfo,
00716 CFSTR("FRAME_PTS"));
00717 CFNumberRef intref = (CFNumberRef)CFDictionaryGetValue(frameInfo,
00718 CFSTR("FRAME_INTERLACED"));
00719 CFNumberRef topref = (CFNumberRef)CFDictionaryGetValue(frameInfo,
00720 CFSTR("FRAME_TFF"));
00721 CFNumberRef repref = (CFNumberRef)CFDictionaryGetValue(frameInfo,
00722 CFSTR("FRAME_REPEAT"));
00723
00724 if (ptsref)
00725 {
00726 CFNumberGetValue(ptsref, kCFNumberSInt64Type, &pts);
00727 CFRelease(ptsref);
00728 }
00729 if (intref)
00730 {
00731 CFNumberGetValue(intref, kCFNumberSInt8Type, &interlaced);
00732 CFRelease(intref);
00733 }
00734 if (topref)
00735 {
00736 CFNumberGetValue(topref, kCFNumberSInt8Type, &topfirst);
00737 CFRelease(topref);
00738 }
00739 if (repref)
00740 {
00741 CFNumberGetValue(repref, kCFNumberSInt8Type, &repeatpic);
00742 CFRelease(repref);
00743 }
00744
00745 int64_t time = (pts != (int64_t)AV_NOPTS_VALUE) ? pts : 0;
00746 {
00747 QMutexLocker lock(&decoder->m_frame_lock);
00748 bool found = false;
00749 int i = 0;
00750 for (; i < decoder->m_decoded_frames.size(); i++)
00751 {
00752 int64_t pts = decoder->m_decoded_frames[i].pts;
00753 if (pts != (int64_t)AV_NOPTS_VALUE && time > pts)
00754 {
00755 found = true;
00756 break;
00757 }
00758 }
00759
00760 VDAFrame frame(CVPixelBufferRetain(imageBuffer), format_type,
00761 pts, interlaced, topfirst, repeatpic);
00762 if (!found)
00763 i = decoder->m_decoded_frames.size();
00764 decoder->m_decoded_frames.insert(i, frame);
00765 decoder->m_frames_decoded++;
00766 }
00767 }