예제 #1
0
void Streamer::h264_send_frame(uint8_t* frame, int frame_size) {
    _frame_type = Source::frame_type(frame[0]);
    SBL_MSG(MSG::STREAMER, "H264 Frame '%c', size %d, timestamp %d", _frame_type, frame_size, _timestamp);
    if (_frame_type == 's' || _frame_type == 'p' || _frame_type == 'I')
        _frame_index = 0;
    if (frame_size <= _packet_size) {
        // small frame, doesn't need to be fragmented
        write_rtp_header(frame - RTP_HEADER, !(frame_type() == 'p' || frame_type() == 's'));
        send_packet(frame - RTP_HEADER, frame_size + RTP_HEADER, true);
    } else {
        // large frame, will have to be segmented.
        create_fu_header(frame);
        // move frame pointer back to make place for RTP header and FU-A (Fragmentation Unit type A) byte
        // FU-A header is in fact NAL header and is already in the frame, but FU-A indicator is not
        frame -= RTP_HEADER + FU_INDICATOR;
        // Only first fragment has FU-A header in the frame, subsequent ones don't and it has to be added
        int first_fragment = FU_HEADER;
        do {
            bool last_packet = frame_size <= _packet_size;
            write_rtp_header(frame, last_packet && !(frame_type() == 'p' || frame_type() == 's'));
            // It is unclear if End bit of FU Header should be set for SPS/PPS frames. I *assume* it does.
            // It probably doesn't matter, because SPS/PPS frames are small and don't need to be fragmented,
            // therefore they don't use FU Header at all ('small frame' 'if' clause above).
            write_fu_header(frame, last_packet);
            send_packet(frame, (frame_size < _packet_size ? frame_size : _packet_size)
                            + RTP_HEADER + FU_INDICATOR + FU_HEADER, last_packet);
            frame += _packet_size;
            frame_size -= _packet_size + first_fragment;
            first_fragment = 0;
        } while (frame_size > 0);
    }
    _frame_index++;
}
예제 #2
0
// send a frame
void Streamer::mpeg4_send_frame(uint8_t* frame, int frame_size) {
    _mp4_starter_frame = (frame[3]==0xb0);
    SBL_MSG(MSG::STREAMER, "MPEG4 Frame '%d', size %d, timestamp %d", _mp4_starter_frame, frame_size, _timestamp);
    if (frame_size <= _packet_size) {
        // small frame, doesn't need to be fragmented
        write_rtp_header(frame - RTP_HEADER, !_mp4_starter_frame);
        send_packet(frame - RTP_HEADER, frame_size + RTP_HEADER, !_mp4_starter_frame);
    } else {
        // large frame, will have to be segmented.
        // move frame pointer back to make place for RTP header bytes
        frame -= RTP_HEADER;
        do {
            bool last_packet = frame_size <= _packet_size;
            write_rtp_header(frame, last_packet);
            send_packet(frame, (frame_size < _packet_size ? frame_size : _packet_size)
                        + RTP_HEADER, last_packet);
            frame += _packet_size;
            frame_size -= _packet_size;
        } while (frame_size > 0);
    }
}
int32_t
create_new_rtp_packet(rtp_packet_builder_t *bldr)
{
    rtp_header_t *rtp;
    mpeg4_es_desc_t *esd;
    size_t alloc_size;

    alloc_size = 0;

    esd = bldr->es_desc;
    rtp = &bldr->header;
    rtp->version = 0x02;
    rtp->padding = 0;
    rtp->extension = 0;
    rtp->CSRC_count = 0;
    rtp->marker = 1;
    rtp->payload_type = bldr->rtp_payload_type;
    rtp->sequence_num++;
    rtp->timestamp = bldr->nal->DTS;

    bldr->payload_size = 0;
    bldr->payload_hdr_size = 0;

    bldr->rtp_pkts = (uint8_t*)nkn_calloc_type(1, RTP_PKT_SIZE +\
					       bldr->mtu_size +\
					       AU_HDR_SIZE, 
					       mod_vpe_rtp_pkt_buf);
    alloc_size = RTP_PKT_SIZE + bldr->mtu_size + AU_HDR_SIZE;

    //bldr->rtp_pkt_size = (int32_t*)nkn_calloc_type(1, sizeof(int32_t));
    //*bldr->rtp_pkt_size = bldr->mtu_size;
    bldr->payload_hdr = bldr->rtp_pkts + 12;
    bldr->payload_hdr_size = 0;

    bldr->payload_writer = bio_init_bitstream(bldr->rtp_pkts, RTP_PKT_SIZE + bldr->mtu_size + AU_HDR_SIZE);//*bldr->rtp_pkt_size);
 
    //write the RTP header
    write_rtp_header(bldr);
    //skip the forbidden section reseverved for AU-HEADERS, we will pack later
    bio_aligned_seek_bitstream(bldr->payload_writer, 12 + AU_HDR_SIZE, SEEK_SET);

    //reserve space for AU-Headers
    bldr->payload_hdr_writer = bio_init_bitstream(bldr->payload_hdr, AU_HDR_SIZE);
    //write the AU-Header Size Field*/
    bio_write_int(bldr->payload_hdr_writer, 0, esd->auh->size_length + esd->auh->index_length);
    //reserve space for AU-Header Size
    bldr->payload_hdr_size += esd->auh->size_length + esd->auh->index_length;

    return 0;

}
예제 #4
0
/*
    JPEG Header, RFC 2435

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Type-specific |              Fragment Offset                  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      Type     |       Q       |     Width     |     Height    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type-specific: 8 bits

   Interpretation depends on the value of the type field.  If no
   interpretation is specified, this field MUST be zeroed on
   transmission and ignored on reception.

Fragment Offset: 24 bits
   The Fragment Offset is the offset in bytes of the current packet in
   the JPEG frame data. This value is encoded in network byte order
   (most significant byte first). The Fragment Offset plus the length of
   the payload data in the packet MUST NOT exceed 2^24 bytes.

Type: 8 bits
   The type field specifies the information that would otherwise be
   present in a JPEG abbreviated table-specification as well as the
   additional JFIF-style parameters not defined by JPEG.  Types 0-63 are
   reserved as fixed, well-known mappings to be defined by this document
   and future revisions of this document.  Types 64-127 are the same as
   types 0-63, except that restart markers are present in the JPEG data
   and a Restart Marker header appears immediately following the main
   JPEG header.  Types 128-255 are free to be dynamically defined by a
   session setup protocol (which is beyond the scope of this document).

Q: 8 bits
   The Q field defines the quantization tables for this frame.  Q values
   0-127 indicate the quantization tables are computed using an
   algorithm determined by the Type field (see below).  Q values 128-255
   indicate that a Quantization Table header appears after the main JPEG
   header (and the Restart Marker header, if present) in the first
   packet of the frame (fragment offset 0).  This header can be used to
   explicitly specify the quantization tables in-band.

Width: 8 bits
   This field encodes the width of the image in 8-pixel multiples (e.g.,
   a width of 40 denotes an image 320 pixels wide).  The maximum width
   is 2040 pixels.

Height: 8 bits
   This field encodes the height of the image in 8-pixel multiples
   (e.g., a height of 30 denotes an image 240 pixels tall). When
   encoding interlaced video, this is the height of a video field, since
   fields are individually JPEG encoded. The maximum height is 2040
   pixels.
*/
void Streamer::mjpeg_send_frame(uint8_t* frame, int frame_size) {
    SBL_MSG(MSG::STREAMER, "MJPEG frame size %d, timestamp %d", frame_size, _timestamp);
    frame -= RTP_HEADER + MJPEG_HEADER;
    uint8_t* frame_start = frame;
    do {
        bool last_packet = frame_size <= _packet_size;
        write_rtp_header(frame, last_packet);
        write_mjpeg_header(frame + RTP_HEADER, frame - frame_start);
        send_packet(frame, (frame_size < _packet_size ? frame_size : _packet_size)
                        + RTP_HEADER + MJPEG_HEADER, last_packet);
        frame      += _packet_size;
        frame_size -= _packet_size;
    } while (frame_size > 0);
}