int qEncodeAPI(QEncoder* encoder, char* bytes, int byteSize)
{
    OSErr err;
    CVPixelBufferPoolRef pixelBufferPool;
    CVPixelBufferRef pixelBuffer;
    unsigned char* baseAddress;
    size_t bufferSize;

    // Grab a pixel buffer from the pool (ICMCompressionSessionEncodeFrame() needs the input
    // data to be passed in as a CVPixelBufferRef).
    pixelBufferPool = ICMCompressionSessionGetPixelBufferPool(encoder->session);
    err = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pixelBufferPool, &pixelBuffer);
    if (err != noErr) {
        fprintf(QSTDERR, "\nqEncodeQT(): could not obtain a pixel buffer from pool");
        fprintf(QSTDERR, "\n\tQUICKTIME ERROR CODE: %d", err);
        return -5;
    }

    // Lock the pixel-buffer so that we can copy our data into it for encoding
    // XXXX: would be nice to avoid this copy.
    err = CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    if (err != noErr) {
        fprintf(QSTDERR, "\nqEncodeQT(): could not lock the pixel buffer");
        fprintf(QSTDERR, "\n\tQUICKTIME ERROR CODE: %d", err);
        CVPixelBufferRelease(pixelBuffer);
        return -5;
    }
    baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);
//	bufferSize = CVPixelBufferGetWidth(pixelBuffer) * CVPixelBufferGetHeight(pixelBuffer) * 4;
    bufferSize = CVPixelBufferGetBytesPerRow(pixelBuffer) * CVPixelBufferGetHeight(pixelBuffer);

    // XXXX: for now, just for debugging.  For production, we should notice if this happens and deal with it "appropriately".
    if (byteSize != bufferSize) {
        fprintf(QSTDERR, "\nqEncodeQT(): input data size (%d) does not match pixel-buffer data size (%d)", byteSize, bufferSize);
    }

    // Copy the data and unlock the buffer
    memcpy(baseAddress, bytes, bufferSize);
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);

    // Encode the frame (now in pixel-buffer form).
    err = ICMCompressionSessionEncodeFrame(	encoder->session,
                                            pixelBuffer,
                                            0, 0, 0, // we're not specifying a frame time
                                            NULL,
                                            NULL,
                                            NULL);
    if (err != noErr) {
        fprintf(QSTDERR, "\nqEncodeQT(): could not encode the frame");
        fprintf(QSTDERR, "\n\tQUICKTIME ERROR CODE: %d", err);
        CVPixelBufferRelease(pixelBuffer);
        return -5;
    }

    CVPixelBufferRelease(pixelBuffer);
    return 0;
}
Exemple #2
0
static void
_frame_decompressed(void *decompressionTrackingRefCon, OSStatus err,
                    ICMDecompressionTrackingFlags dtf,
                    CVPixelBufferRef pixelBuffer, TimeValue64 displayTime,
                    TimeValue64 displayDuration,
                    ICMValidTimeFlags validTimeFlags, void *reserved,
                    void *sourceFrameRefCon)
{
    dbg_printf("[ vOE]  >> [%08lx] :: _frame_decompressed()\n", (UInt32) -1);
    if (!err) {
        StreamInfoPtr si = (StreamInfoPtr) decompressionTrackingRefCon;
        if (dtf & kICMDecompressionTracking_ReleaseSourceData) {
            // if we were responsible for managing source data buffers,
            //  we should release the source buffer here,
            //  using sourceFrameRefCon to identify it.
        }

        if ((dtf & kICMDecompressionTracking_EmittingFrame) && pixelBuffer) {
            ICMCompressionFrameOptionsRef frameOptions = NULL;
            OSType pf = CVPixelBufferGetPixelFormatType(pixelBuffer);

            dbg_printf("[ vOE]   > [%08lx] :: _frame_decompressed() = %ld; %ld,"
                       " %lld, %lld, %ld [%ld '%4.4s' (%ld x %ld)]\n",
                       (UInt32) -1, err,
                       dtf, displayTime, displayDuration, validTimeFlags,
                       CVPixelBufferGetDataSize(pixelBuffer), (char *) &pf,
                       CVPixelBufferGetWidth(pixelBuffer),
                       CVPixelBufferGetHeight(pixelBuffer));

            displayDuration = 25; //?

            // Feed the frame to the compression session.
            err = ICMCompressionSessionEncodeFrame(si->si_v.cs, pixelBuffer,
                                                   displayTime, displayDuration,
                                                   validTimeFlags, frameOptions,
                                                   NULL, NULL );
        }
    }

    dbg_printf("[ vOE] <   [%08lx] :: _frame_decompressed() = %ld\n",
               (UInt32) -1, err);
}
Exemple #3
0
static int quicktimedrv_record(screenshot_t *screenshot)
{
    if (!video_ready) {
        return 0;
    }

    OSErr theError;

    // lock buffer
    theError = CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    if (theError) {
        log_debug("quicktime: error locking pixel buffer!");
        return -1;
    }

    // fill frame
    unsigned char *buffer = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuffer);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);

    unsigned int line_size = screenshot->draw_buffer_line_size;
    int h = screenshot->height;
    int w = screenshot->width;
    int xoff = screenshot->x_offset;
    int yoff = screenshot->y_offset;
    BYTE *srcBuffer = screenshot->draw_buffer;

    // move to last line in tgt buffer and to first in source
    buffer += (video_yoff) * bytesPerRow + video_xoff * 3;
    srcBuffer += yoff * line_size + xoff;

    int x, y;
    for (y = 0; y < h; y++) {
        int pix = 0;
        for (x = 0; x < w; x++) {
            BYTE val = srcBuffer[x];
            buffer[pix++] = screenshot->palette->entries[val].red;
            buffer[pix++] = screenshot->palette->entries[val].green;
            buffer[pix++] = screenshot->palette->entries[val].blue;
        }
        buffer += bytesPerRow;
        srcBuffer += line_size;
    }

    // unlock buffer
    theError = CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    if (theError) {
        log_debug("quicktime: error unlocking pixel buffer!");
        return -1;
    }

    TimeValue64 next = CVGetCurrentHostTime() / divider;
    TimeValue64 duration = next - timestamp;
    timestamp = next;

    // encode frame
    theError = ICMCompressionSessionEncodeFrame(videoCompressionSession,
                                                pixelBuffer,
                                                timestamp, duration,
                                                kICMValidTime_DisplayTimeStampIsValid |
                                                kICMValidTime_DisplayDurationIsValid,
                                                NULL, NULL, (void *)NULL);
    if (theError) {
        log_debug("quicktime: error encoding frame!");
        return -1;
    }

    return 0;
}