Ejemplo n.º 1
0
static void upipe_rtp_h264_output_nalu(struct upipe *upipe,
                                       uint8_t nalu,
                                       struct uref *uref,
                                       struct upump **upump_p)
{
    size_t size = 0;
    if (unlikely(!ubase_check(uref_block_size(uref, &size)))) {
        upipe_err(upipe, "fail to get block size");
        return;
    }

    bool split = size > RTP_SPLIT_SIZE;
    uint32_t fragment = 0;

    while (size) {
        bool last_fragment = size <= RTP_SPLIT_SIZE;
        size_t split_size = last_fragment ? size : RTP_SPLIT_SIZE;
        uint8_t hdr[2] = { nalu, 0 };
        size_t hdr_size = 1;

        if (split) {
            if (!fragment)
                hdr[1] = FU_START;
            else if (last_fragment)
                hdr[1] = FU_END;
            hdr[1] |= NALU_TYPE(hdr[0]);

            hdr[0] = NALU_F(hdr[0]) | NALU_NRI(hdr[0]) | FU_A;
            hdr_size++;
        }

        struct uref *next = NULL;
        if (!last_fragment) {
            next = uref_block_split(uref, split_size);
            if (unlikely(next == NULL)) {
                upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
                return;
            }
        }

        /* FIXME should require a ubuf_mgr */
        struct ubuf *header =
                ubuf_block_alloc(uref->ubuf->mgr, hdr_size * sizeof (hdr[0]));
        if (unlikely(header == NULL)) {
            upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
            uref_free(uref);
            uref_free(next);
            return;
        }

        uint8_t *buf = NULL;
        int buf_size = hdr_size;
        ubuf_block_write(header, 0, &buf_size, &buf);
        memcpy(buf, hdr, hdr_size * sizeof (hdr[0]));
        ubuf_block_unmap(header, 0);

        /* append payload (current ubuf) to header to form segmented ubuf */
        struct ubuf *payload = uref_detach_ubuf(uref);
        if (unlikely(!ubase_check(ubuf_block_append(header, payload)))) {
            upipe_warn(upipe, "could not append payload to header");
            ubuf_free(header);
            ubuf_free(payload);
            uref_free(uref);
            uref_free(next);
            return;
        }
        uref_attach_ubuf(uref, header);
        uref_clock_set_cr_dts_delay(uref, 0);
        upipe_rtp_h264_output(upipe, uref, upump_p);
        size -= split_size;
        fragment++;
        uref = next;
    }
}
Ejemplo n.º 2
0
bool OutNetRTMP4TSStream::FeedVideoData(uint8_t *pData, uint32_t dataLength,
		double absoluteTimestamp) {
	switch (NALU_TYPE(pData[0])) {
		case NALU_TYPE_SPS:
		{
			//1. Prepare the SPS part from video codec
			if (dataLength > 128) {
				FATAL("SPS too big");
				return false;
			}
			memcpy(_pSPSPPS + 6, pData + 1, 3); //profile,profile compat,level
			EHTONSP(_pSPSPPS + 11, (uint16_t) dataLength);
			memcpy(_pSPSPPS + 13, pData, dataLength);
			_PPSStart = 13 + dataLength;
			_spsAvailable = true;
			return true;
		}
		case NALU_TYPE_PPS:
		{
			//2. Prepare the PPS part from video codec
			if (dataLength > 128) {
				FATAL("PPS too big");
				return false;
			}
			if (!_spsAvailable) {
				WARN("No SPS available yet");
				return true;
			}

			_pSPSPPS[_PPSStart] = 1;
			EHTONSP(_pSPSPPS + _PPSStart + 1, (uint16_t) dataLength);
			memcpy(_pSPSPPS + _PPSStart + 1 + 2, pData, dataLength);
			_spsAvailable = false;

			//3. Send the video codec
			if (!BaseOutNetRTMPStream::FeedData(
					_pSPSPPS, //pData
					_PPSStart + 1 + 2 + dataLength, //dataLength
					0, //processedLength
					_PPSStart + 1 + 2 + dataLength, //totalLength
					absoluteTimestamp, //absoluteTimestamp
					false //isAudio
					)) {
				FATAL("Unable to send video codec setup");
				return false;
			}

			_videoCodecSent = true;

			return true;
		}
		case NALU_TYPE_IDR:
		case NALU_TYPE_SLICE:
		{
			//10. Make room for the RTMP header
			_videoBuffer.ReadFromRepeat(0, 9);

			//11. Add the raw data
			_videoBuffer.ReadFromBuffer(pData, dataLength);

			uint8_t *pBuffer = GETIBPOINTER(_videoBuffer);

			//12. Setup the RTMP header
			pBuffer[0] = (NALU_TYPE(pData[0]) == NALU_TYPE_IDR) ? 0x17 : 0x27;
			pBuffer[1] = 0x01;
			pBuffer[2] = pBuffer[3] = pBuffer[4] = 0;
			EHTONLP(pBuffer + 5, dataLength); //----MARKED-LONG---

			//13. Send it
			if (!BaseOutNetRTMPStream::FeedData(
					pBuffer, //pData
					dataLength + 9, //dataLength
					0, //processedLength
					dataLength + 9, //totalLength
					absoluteTimestamp, //absoluteTimestamp
					false //isAudio
					)) {
				FATAL("Unable to send video");
				return false;
			}

			//14. Cleanup
			_videoBuffer.IgnoreAll();

			return true;
		}
		case NALU_TYPE_PD:
		case NALU_TYPE_SEI:
		case NALU_TYPE_FILL:
		{
			return true;
		}
		default:
		{
			WARN("Ignoring NAL: %s", STR(NALUToString(pData[0])));
			return true;
		}
	}
}