th_pkt_t * avc_convert_pkt(th_pkt_t *src) { th_pkt_t *pkt = malloc(sizeof(th_pkt_t)); *pkt = *src; pkt->pkt_refcount = 1; pkt->pkt_header = NULL; pkt->pkt_payload = NULL; if (src->pkt_header) { sbuf_t headers; sbuf_init(&headers); isom_write_avcc(&headers, pktbuf_ptr(src->pkt_header), pktbuf_len(src->pkt_header)); pkt->pkt_header = pktbuf_make(headers.sb_data, headers.sb_ptr); } sbuf_t payload; sbuf_init(&payload); if(src->pkt_header) avc_parse_nal_units(&payload, pktbuf_ptr(src->pkt_header), pktbuf_len(src->pkt_header)); avc_parse_nal_units(&payload, pktbuf_ptr(src->pkt_payload), pktbuf_len(src->pkt_payload)); pkt->pkt_payload = pktbuf_make(payload.sb_data, payload.sb_ptr); pkt_ref_dec(src); return pkt; }
int CDVDVideoCodecVDA::Decode(BYTE* pData, int iSize, double dts, double pts) { CCocoaAutoPool pool; // if (pData) { OSStatus status; double sort_time; uint32_t avc_flags = 0; CFDataRef avc_demux; CFDictionaryRef avc_time; if (m_convert_bytestream) { // convert demuxer packet from bytestream (AnnexB) to bitstream ByteIOContext *pb; int demuxer_bytes; uint8_t *demuxer_content; if(m_dllAvFormat->url_open_dyn_buf(&pb) < 0) { return VC_ERROR; } demuxer_bytes = avc_parse_nal_units(m_dllAvFormat, pb, pData, iSize); demuxer_bytes = m_dllAvFormat->url_close_dyn_buf(pb, &demuxer_content); avc_demux = CFDataCreate(kCFAllocatorDefault, demuxer_content, demuxer_bytes); m_dllAvUtil->av_free(demuxer_content); } else { avc_demux = CFDataCreate(kCFAllocatorDefault, pData, iSize); } sort_time = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency(); avc_time = CreateDictionaryWithDisplayTime(sort_time - m_sort_time_offset, dts, pts); if (m_DropPictures) avc_flags = kVDADecoderDecodeFlags_DontEmitFrame; status = m_dll->VDADecoderDecode((VDADecoder)m_vda_decoder, avc_flags, avc_demux, avc_time); CFRelease(avc_time); CFRelease(avc_demux); if (status != kVDADecoderNoErr) { CLog::Log(LOGNOTICE, "%s - VDADecoderDecode failed, status(%d)", __FUNCTION__, (int)status); return VC_ERROR; } } // TODO: queue depth is related to the number of reference frames in encoded h.264. // so we need to buffer until we get N ref frames + 1. if (m_queue_depth < 4) { return VC_BUFFER; } return VC_PICTURE | VC_BUFFER; }
static int avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) { sbuf_t sb; sbuf_init(&sb); avc_parse_nal_units(&sb, buf_in, *size); free(*buf); *buf = sb.sb_data; *size = sb.sb_ptr; return 0; }
const int avc_parse_nal_units_buf(DllAvUtil *av_util_ctx, DllAvFormat *av_format_ctx, const uint8_t *buf_in, uint8_t **buf, int *size) { ByteIOContext *pb; int ret = av_format_ctx->url_open_dyn_buf(&pb); if (ret < 0) return ret; avc_parse_nal_units(av_format_ctx, pb, buf_in, *size); av_util_ctx->av_freep(buf); *size = av_format_ctx->url_close_dyn_buf(pb, buf); return 0; }
const int avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) { AVIOContext *pb; int ret = avio_open_dyn_buf(&pb); if (ret < 0) return ret; avc_parse_nal_units(pb, buf_in, *size); av_freep(buf); *size = avio_close_dyn_buf(pb, buf); return 0; }
int PrivateDecoderVDA::GetFrame(AVStream *stream, AVFrame *picture, int *got_picture_ptr, AVPacket *pkt) { if (!pkt) CocoaAutoReleasePool pool; int result = -1; if (!m_lib || !stream) return result; AVCodecContext *avctx = stream->codec; if (!avctx) return result; if (pkt) { CFDataRef avc_demux; CFDictionaryRef params; if (m_annexb) { // convert demuxer packet from bytestream (AnnexB) to bitstream AVIOContext *pb; int demuxer_bytes; uint8_t *demuxer_content; if(avio_open_dyn_buf(&pb) < 0) { return result; } demuxer_bytes = avc_parse_nal_units(pb, pkt->data, pkt->size); demuxer_bytes = avio_close_dyn_buf(pb, &demuxer_content); avc_demux = CFDataCreate(kCFAllocatorDefault, demuxer_content, demuxer_bytes); av_free(demuxer_content); } else if (m_convert_3byteTo4byteNALSize) { // convert demuxer packet from 3 byte NAL sizes to 4 byte AVIOContext *pb; if (avio_open_dyn_buf(&pb) < 0) { return result; } uint32_t nal_size; uint8_t *end = pkt->data + pkt->size; uint8_t *nal_start = pkt->data; while (nal_start < end) { nal_size = VDA_RB24(nal_start); avio_wb32(pb, nal_size); nal_start += 3; avio_write(pb, nal_start, nal_size); nal_start += nal_size; } uint8_t *demuxer_content; int demuxer_bytes = avio_close_dyn_buf(pb, &demuxer_content); avc_demux = CFDataCreate(kCFAllocatorDefault, demuxer_content, demuxer_bytes); av_free(demuxer_content); } else { avc_demux = CFDataCreate(kCFAllocatorDefault, pkt->data, pkt->size); } CFStringRef keys[4] = { CFSTR("FRAME_PTS"), CFSTR("FRAME_INTERLACED"), CFSTR("FRAME_TFF"), CFSTR("FRAME_REPEAT") }; CFNumberRef values[5]; values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &pkt->pts); values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &picture->interlaced_frame); values[2] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &picture->top_field_first); values[3] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &picture->repeat_pict); params = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&keys, (const void **)&values, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); INIT_ST; vda_st = m_lib->decoderDecode((VDADecoder)m_decoder, 0, avc_demux, params); CHECK_ST; if (vda_st == kVDADecoderNoErr) result = pkt->size; CFRelease(avc_demux); CFRelease(params); } if (m_decoded_frames.size() < m_max_ref_frames) return result; *got_picture_ptr = 1; m_frame_lock.lock(); VDAFrame vdaframe = m_decoded_frames.takeLast(); m_frame_lock.unlock(); if (avctx->get_buffer(avctx, picture) < 0) return -1; picture->reordered_opaque = vdaframe.pts; picture->interlaced_frame = vdaframe.interlaced_frame; picture->top_field_first = vdaframe.top_field_first; picture->repeat_pict = vdaframe.repeat_pict; VideoFrame *frame = (VideoFrame*)picture->opaque; PixelFormat in_fmt = PIX_FMT_NONE; PixelFormat out_fmt = PIX_FMT_NONE; if (vdaframe.format == 'BGRA') in_fmt = PIX_FMT_BGRA; else if (vdaframe.format == '2vuy') in_fmt = PIX_FMT_UYVY422; if (frame->codec == FMT_YV12) out_fmt = PIX_FMT_YUV420P; if (out_fmt != PIX_FMT_NONE && in_fmt != PIX_FMT_NONE && frame->buf) { CVPixelBufferLockBaseAddress(vdaframe.buffer, 0); uint8_t* base = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(vdaframe.buffer, 0); AVPicture img_in, img_out; avpicture_fill(&img_out, (uint8_t *)frame->buf, out_fmt, frame->width, frame->height); avpicture_fill(&img_in, base, in_fmt, frame->width, frame->height); myth_sws_img_convert(&img_out, out_fmt, &img_in, in_fmt, frame->width, frame->height); CVPixelBufferUnlockBaseAddress(vdaframe.buffer, 0); } else { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to convert decoded frame."); } CVPixelBufferRelease(vdaframe.buffer); return result; }