/** @internal @This catches events thrown by pipes. * * @param uprobe pointer to probe * @param upipe pointer to pipe throwing the event * @param event event thrown * @param args optional event-specific parameters * @return an error code */ static int uprobe_upump_mgr_throw(struct uprobe *uprobe, struct upipe *upipe, int event, va_list args) { struct uprobe_upump_mgr *uprobe_upump_mgr = uprobe_upump_mgr_from_uprobe(uprobe); switch (event) { default: return uprobe_throw_next(uprobe, upipe, event, args); case UPROBE_FREEZE_UPUMP_MGR: case UPROBE_THAW_UPUMP_MGR: uprobe_upump_mgr->frozen = event == UPROBE_FREEZE_UPUMP_MGR; return UBASE_ERR_NONE; case UPROBE_NEED_UPUMP_MGR: break; } if (uprobe_upump_mgr->frozen || uprobe_upump_mgr->upump_mgr == NULL) return uprobe_throw_next(uprobe, upipe, event, args); struct upump_mgr **upump_mgr_p = va_arg(args, struct upump_mgr **); *upump_mgr_p = upump_mgr_use(uprobe_upump_mgr->upump_mgr); return UBASE_ERR_NONE; }
/** @This changes the upump_mgr set by this probe. * * @param uprobe pointer to probe * @param upump_mgr new upump manager to provide to pipes */ void uprobe_upump_mgr_set(struct uprobe *uprobe, struct upump_mgr *upump_mgr) { struct uprobe_upump_mgr *uprobe_upump_mgr = uprobe_upump_mgr_from_uprobe(uprobe); upump_mgr_release(uprobe_upump_mgr->upump_mgr); uprobe_upump_mgr->upump_mgr = upump_mgr_use(upump_mgr); }
/** @internal @This handles audio input. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to upump structure */ static void upipe_osx_audioqueue_sink_input_audio(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_osx_audioqueue_sink *osx_audioqueue = upipe_osx_audioqueue_sink_from_upipe(upipe); struct AudioQueueBuffer *qbuf; size_t size = 0; if (unlikely(!ubase_check(uref_block_size(uref, &size)))) { upipe_warn(upipe, "could not get block size"); uref_free(uref); return; } /* TODO block ? */ #if 0 upump_mgr_use(upump->mgr); upump_mgr_sink_block(upump->mgr); #endif /* allocate queue buf, extract block, enqueue * Audioqueue has no support for "external" buffers */ AudioQueueAllocateBuffer(osx_audioqueue->queue, size, &qbuf); uref_block_extract(uref, 0, -1, qbuf->mAudioData); qbuf->mAudioDataByteSize = size; qbuf->mUserData = (*upump_p)->mgr; AudioQueueEnqueueBuffer(osx_audioqueue->queue, qbuf, 0, NULL); uref_free(uref); }
/** @This initializes an already allocated uprobe_upump_mgr structure. * * @param uprobe_upump_mgr pointer to the already allocated structure * @param next next probe to test if this one doesn't catch the event * @param upump_mgr upump manager to provide to pipes * @return pointer to uprobe, or NULL in case of error */ struct uprobe *uprobe_upump_mgr_init(struct uprobe_upump_mgr *uprobe_upump_mgr, struct uprobe *next, struct upump_mgr *upump_mgr) { assert(uprobe_upump_mgr != NULL); struct uprobe *uprobe = uprobe_upump_mgr_to_uprobe(uprobe_upump_mgr); uprobe_upump_mgr->upump_mgr = upump_mgr_use(upump_mgr); uprobe_upump_mgr->frozen = false; uprobe_init(uprobe, uprobe_upump_mgr_throw, next); return uprobe; }
/** @internal @This handles packets. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump upump structure */ static void upipe_avcdec_input_packet(struct upipe *upipe, struct uref *uref, struct upump *upump) { uint8_t *inbuf; size_t insize = 0; struct upipe_avcdec *upipe_avcdec = upipe_avcdec_from_upipe(upipe); assert(upipe); assert(uref); if (upipe_avcdec->upump_av_deal) { /* pending open_codec callback */ upipe_dbg(upipe, "Received packet while open_codec pending"); if (upump) { upump_mgr_sink_block(upump->mgr); upump_mgr_use(upump->mgr); upipe_avcdec->saved_upump_mgr = upump->mgr; } if (upipe_avcdec->saved_uref) { upipe_warn(upipe, "Dropping previously saved packet !"); uref_free(upipe_avcdec->saved_uref); } upipe_avcdec->saved_uref = uref; return; } else if (upipe_avcdec->saved_uref) { upipe_dbg(upipe, "Processing previously saved packet"); struct uref *prev_uref = upipe_avcdec->saved_uref; upipe_avcdec->saved_uref = NULL; /* Not a typo, using the current upump here */ upipe_avcdec_input_packet(upipe, prev_uref, upump); } if (!upipe_avcdec->context) { uref_free(uref); upipe_warn(upipe, "Received packet but decoder is not initialized"); return; } /* avcodec input buffer needs to be at least 4-byte aligned and FF_INPUT_BUFFER_PADDING_SIZE larger than actual input size. Thus, extract ubuf content in a properly allocated buffer. Padding must be zeroed. */ uref_block_size(uref, &insize); if (unlikely(!insize)) { upipe_warn(upipe, "Received packet with size 0, dropping"); uref_free(uref); return; } upipe_dbg_va(upipe, "Received packet %u - size : %u", upipe_avcdec->counter, insize); inbuf = malloc(insize + FF_INPUT_BUFFER_PADDING_SIZE); if (unlikely(!inbuf)) { upipe_throw_aerror(upipe); return; } memset(inbuf, 0, insize + FF_INPUT_BUFFER_PADDING_SIZE); uref_block_extract(uref, 0, insize, inbuf); ubuf_free(uref_detach_ubuf(uref)); uref_pic_set_number(uref, upipe_avcdec->counter); /* Track current uref in pipe structure - required for buffer allocation * in upipe_avcdec_get_buffer */ upipe_avcdec->uref = uref; upipe_avcdec_process_buf(upipe, inbuf, insize, upump); free(inbuf); uref_free(uref); upipe_avcdec->counter++; }