int PrivateDecoderCrystalHD::GetFrame(AVStream *stream,
                                      AVFrame *picture,
                                      int *got_picture_ptr,
                                      AVPacket *pkt)
{
    int result = -1;
    if (!stream || !m_device || !picture)
        return result;

    AVCodecContext *avctx = stream->codec;
    if (!avctx || !StartFetcherThread())
        return result;

    if (pkt && pkt->size)
    {
        result = ProcessPacket(stream, pkt);
        if (result < 0)
            return result;
    }

    m_decoded_frames_lock.lock();
    int available = m_decoded_frames.size();
    m_decoded_frames_lock.unlock();
    if (!available)
        return result;

    if (avctx->get_buffer2(avctx, picture, 0) < 0)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            QString("%1 decoded frames available but no video buffers.")
                .arg(available));
        return -1;
    }

    m_decoded_frames_lock.lock();
    VideoFrame *frame = m_decoded_frames.takeLast();
    m_decoded_frames_lock.unlock();

    *got_picture_ptr = 1;
    picture->reordered_opaque = (int64_t)(frame->timecode /
                                          av_q2d(stream->time_base) / 10000000);
    LOG(VB_TIMESTAMP, LOG_DEBUG, LOC +
        QString("decoder output timecode %1 ms (pts %2)")
            .arg(frame->timecode / 10000).arg(picture->reordered_opaque));
    copy((VideoFrame*)picture->opaque, frame);
    if (frame->priv[0] && frame->qstride)
    {
        memcpy(picture->atsc_cc_buf, frame->priv[0], frame->qstride);
        picture->atsc_cc_len = frame->qstride;
    }
    free_frame(frame);
    return result;
}
Exemplo n.º 2
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_buffer2(avctx, picture, 0) < 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;

    AVPixelFormat in_fmt  = AV_PIX_FMT_NONE;
    if (vdaframe.format == 'BGRA')
        in_fmt = AV_PIX_FMT_BGRA;
    else if (vdaframe.format == '2vuy')
        in_fmt = AV_PIX_FMT_UYVY422;

    if (frame->codec == FMT_YV12 && in_fmt != AV_PIX_FMT_NONE && frame->buf)
    {
        CVPixelBufferLockBaseAddress(vdaframe.buffer, 0);
        uint8_t* base = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(vdaframe.buffer, 0);
        AVPicture img_in;
        avpicture_fill(&img_in, base, in_fmt, frame->width, frame->height);
        m_copyCtx.Copy(frame, &img_in, in_fmt);
        CVPixelBufferUnlockBaseAddress(vdaframe.buffer, 0);
    }
    else
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to convert decoded frame.");
    }

    CVPixelBufferRelease(vdaframe.buffer);
    return result;
}