/** return 0 on packet, <0 on partial packet or error... */ static int svq3_parse_packet (AVFormatContext *s, PayloadContext *sv, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags) { int config_packet, start_packet, end_packet; if (len < 2) return AVERROR_INVALIDDATA; config_packet = buf[0] & 0x40; start_packet = buf[0] & 0x20; end_packet = buf[0] & 0x10; buf += 2; // ignore buf[1] len -= 2; if (config_packet) { av_freep(&st->codec->extradata); st->codec->extradata_size = 0; if (len < 2 || ff_alloc_extradata(st->codec, len + 8)) return AVERROR_INVALIDDATA; memcpy(st->codec->extradata, "SEQH", 4); AV_WB32(st->codec->extradata + 4, len); memcpy(st->codec->extradata + 8, buf, len); /* We set codec_id to AV_CODEC_ID_NONE initially to * delay decoder initialization since extradata is * carried within the RTP stream, not SDP. Here, * by setting codec_id to AV_CODEC_ID_SVQ3, we are signalling * to the decoder that it is OK to initialize. */ st->codec->codec_id = AV_CODEC_ID_SVQ3; return AVERROR(EAGAIN); } if (start_packet) { int res; if (sv->pktbuf) { uint8_t *tmp; avio_close_dyn_buf(sv->pktbuf, &tmp); av_free(tmp); } if ((res = avio_open_dyn_buf(&sv->pktbuf)) < 0) return res; sv->timestamp = *timestamp; } if (!sv->pktbuf) return AVERROR_INVALIDDATA; avio_write(sv->pktbuf, buf, len); if (end_packet) { int ret = ff_rtp_finalize_packet(pkt, &sv->pktbuf, st->index); if (ret < 0) return ret; *timestamp = sv->timestamp; return 0; } return AVERROR(EAGAIN); }
static int mpa_robust_parse_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags) { unsigned adu_size, continuation; int err, header_size; if (!buf) { buf = &data->split_buf[data->split_pos]; len = data->split_buf_size - data->split_pos; header_size = mpa_robust_parse_rtp_header(ctx, buf, len, &adu_size, &continuation); if (header_size < 0) { av_freep(&data->split_buf); return header_size; } buf += header_size; len -= header_size; if (continuation || adu_size > len) { av_freep(&data->split_buf); av_log(ctx, AV_LOG_ERROR, "Invalid frame\n"); return AVERROR_INVALIDDATA; } if (av_new_packet(pkt, adu_size)) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); return AVERROR(ENOMEM); } pkt->stream_index = st->index; memcpy(pkt->data, buf, adu_size); data->split_pos += header_size + adu_size; if (data->split_pos == data->split_buf_size) { av_freep(&data->split_buf); return 0; } return 1; } header_size = mpa_robust_parse_rtp_header(ctx, buf, len, &adu_size, &continuation); if (header_size < 0) return header_size; buf += header_size; len -= header_size; if (!continuation && adu_size <= len) { /* One or more complete frames */ if (av_new_packet(pkt, adu_size)) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); return AVERROR(ENOMEM); } pkt->stream_index = st->index; memcpy(pkt->data, buf, adu_size); buf += adu_size; len -= adu_size; if (len) { data->split_buf_size = len; data->split_buf = av_malloc(data->split_buf_size); data->split_pos = 0; if (!data->split_buf) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); av_free_packet(pkt); return AVERROR(ENOMEM); } memcpy(data->split_buf, buf, data->split_buf_size); return 1; } return 0; } else if (!continuation) { /* && adu_size > len */ /* First fragment */ ffio_free_dyn_buf(&data->fragment); data->adu_size = adu_size; data->cur_size = len; data->timestamp = *timestamp; err = avio_open_dyn_buf(&data->fragment); if (err < 0) return err; avio_write(data->fragment, buf, len); return AVERROR(EAGAIN); } /* else continuation == 1 */ /* Fragment other than first */ if (!data->fragment) { av_log(ctx, AV_LOG_WARNING, "Received packet without a start fragment; dropping.\n"); return AVERROR(EAGAIN); } if (adu_size = data->adu_size || data->timestamp != *timestamp) { ffio_free_dyn_buf(&data->fragment); av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n"); return AVERROR_INVALIDDATA; } avio_write(data->fragment, buf, len); data->cur_size += len; if (data->cur_size < data->adu_size) return AVERROR(EAGAIN); err = ff_rtp_finalize_packet(pkt, &data->fragment, st->index); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Error occurred when getting fragment buffer.\n"); return err; } return 0; }
static int jpeg_parse_packet(AVFormatContext *ctx, PayloadContext *jpeg, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags) { uint8_t type, q, width, height; const uint8_t *qtables = NULL; uint16_t qtable_len; uint32_t off; int ret, dri = 0; if (len < 8) { av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n"); return AVERROR_INVALIDDATA; } /* Parse the main JPEG header. */ off = AV_RB24(buf + 1); /* fragment byte offset */ type = AV_RB8(buf + 4); /* id of jpeg decoder params */ q = AV_RB8(buf + 5); /* quantization factor (or table id) */ width = AV_RB8(buf + 6); /* frame width in 8 pixel blocks */ height = AV_RB8(buf + 7); /* frame height in 8 pixel blocks */ buf += 8; len -= 8; if (type & 0x40) { if (len < 4) { av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n"); return AVERROR_INVALIDDATA; } dri = AV_RB16(buf); buf += 4; len -= 4; type &= ~0x40; } /* Parse the restart marker header. */ if (type > 63) { av_log(ctx, AV_LOG_ERROR, "Unimplemented RTP/JPEG restart marker header.\n"); return AVERROR_PATCHWELCOME; } if (type > 1) { av_log(ctx, AV_LOG_ERROR, "Unimplemented RTP/JPEG type %d\n", type); return AVERROR_PATCHWELCOME; } /* Parse the quantization table header. */ if (off == 0) { /* Start of JPEG data packet. */ uint8_t new_qtables[128]; uint8_t hdr[1024]; if (q > 127) { uint8_t precision; if (len < 4) { av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n"); return AVERROR_INVALIDDATA; } /* The first byte is reserved for future use. */ precision = AV_RB8(buf + 1); /* size of coefficients */ qtable_len = AV_RB16(buf + 2); /* length in bytes */ buf += 4; len -= 4; if (precision) av_log(ctx, AV_LOG_WARNING, "Only 8-bit precision is supported.\n"); if (qtable_len > 0) { if (len < qtable_len) { av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n"); return AVERROR_INVALIDDATA; } qtables = buf; buf += qtable_len; len -= qtable_len; if (q < 255) { if (jpeg->qtables_len[q - 128] && (jpeg->qtables_len[q - 128] != qtable_len || memcmp(qtables, &jpeg->qtables[q - 128][0], qtable_len))) { av_log(ctx, AV_LOG_WARNING, "Quantization tables for q=%d changed\n", q); } else if (!jpeg->qtables_len[q - 128] && qtable_len <= 128) { memcpy(&jpeg->qtables[q - 128][0], qtables, qtable_len); jpeg->qtables_len[q - 128] = qtable_len; } } } else { if (q == 255) { av_log(ctx, AV_LOG_ERROR, "Invalid RTP/JPEG packet. Quantization tables not found.\n"); return AVERROR_INVALIDDATA; } if (!jpeg->qtables_len[q - 128]) { av_log(ctx, AV_LOG_ERROR, "No quantization tables known for q=%d yet.\n", q); return AVERROR_INVALIDDATA; } qtables = &jpeg->qtables[q - 128][0]; qtable_len = jpeg->qtables_len[q - 128]; } } else { /* q <= 127 */ if (q == 0 || q > 99) { av_log(ctx, AV_LOG_ERROR, "Reserved q value %d\n", q); return AVERROR_INVALIDDATA; } create_default_qtables(new_qtables, q); qtables = new_qtables; qtable_len = sizeof(new_qtables); } /* Skip the current frame in case of the end packet * has been lost somewhere. */ free_frame_if_needed(jpeg); if ((ret = avio_open_dyn_buf(&jpeg->frame)) < 0) return ret; jpeg->timestamp = *timestamp; /* Generate a frame and scan headers that can be prepended to the * RTP/JPEG data payload to produce a JPEG compressed image in * interchange format. */ jpeg->hdr_size = jpeg_create_header(hdr, sizeof(hdr), type, width, height, qtables, qtable_len / 64, dri); /* Copy JPEG header to frame buffer. */ avio_write(jpeg->frame, hdr, jpeg->hdr_size); } if (!jpeg->frame) { av_log(ctx, AV_LOG_ERROR, "Received packet without a start chunk; dropping frame.\n"); return AVERROR(EAGAIN); } if (jpeg->timestamp != *timestamp) { /* Skip the current frame if timestamp is incorrect. * A start packet has been lost somewhere. */ free_frame_if_needed(jpeg); av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match.\n"); return AVERROR_INVALIDDATA; } if (off != avio_tell(jpeg->frame) - jpeg->hdr_size) { av_log(ctx, AV_LOG_ERROR, "Missing packets; dropping frame.\n"); return AVERROR(EAGAIN); } /* Copy data to frame buffer. */ avio_write(jpeg->frame, buf, len); if (flags & RTP_FLAG_MARKER) { /* End of JPEG data packet. */ uint8_t buf[2] = { 0xff, EOI }; /* Put EOI marker. */ avio_write(jpeg->frame, buf, sizeof(buf)); /* Prepare the JPEG packet. */ if ((ret = ff_rtp_finalize_packet(pkt, &jpeg->frame, st->index)) < 0) { av_log(ctx, AV_LOG_ERROR, "Error occurred when getting frame buffer.\n"); return ret; } return 0; } return AVERROR(EAGAIN); }
static int ac3_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags) { unsigned frame_type; unsigned nr_frames; int err; if (len < RTP_AC3_PAYLOAD_HEADER_SIZE + 1) { av_log(ctx, AV_LOG_ERROR, "Invalid %d bytes packet\n", len); return AVERROR_INVALIDDATA; } frame_type = buf[0] & 0x3; nr_frames = buf[1]; buf += RTP_AC3_PAYLOAD_HEADER_SIZE; len -= RTP_AC3_PAYLOAD_HEADER_SIZE; switch (frame_type) { case 0: /* One or more complete frames */ if (!nr_frames) { av_log(ctx, AV_LOG_ERROR, "Invalid AC3 packet data\n"); return AVERROR_INVALIDDATA; } if (av_new_packet(pkt, len)) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); return AVERROR(ENOMEM); } pkt->stream_index = st->index; memcpy(pkt->data, buf, len); return 0; case 1: case 2: /* First fragment */ ffio_free_dyn_buf(&data->fragment); data->last_frame = 1; data->nr_frames = nr_frames; err = avio_open_dyn_buf(&data->fragment); if (err < 0) return err; avio_write(data->fragment, buf, len); data->timestamp = *timestamp; return AVERROR(EAGAIN); case 3: /* Fragment other than first */ if (!data->fragment) { av_log(ctx, AV_LOG_WARNING, "Received packet without a start fragment; dropping.\n"); return AVERROR(EAGAIN); } if (nr_frames != data->nr_frames || data->timestamp != *timestamp) { ffio_free_dyn_buf(&data->fragment); av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n"); return AVERROR_INVALIDDATA; } avio_write(data->fragment, buf, len); data->last_frame++; } if (!(flags & RTP_FLAG_MARKER)) return AVERROR(EAGAIN); if (data->last_frame != data->nr_frames) { ffio_free_dyn_buf(&data->fragment); av_log(ctx, AV_LOG_ERROR, "Missed %d packets\n", data->nr_frames - data->last_frame); return AVERROR_INVALIDDATA; } err = ff_rtp_finalize_packet(pkt, &data->fragment, st->index); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Error occurred when getting fragment buffer.\n"); return err; } return 0; }