static int iff_read_header(AVFormatContext *s) { IffDemuxContext *iff = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; uint8_t *buf; uint32_t chunk_id, data_size; uint32_t screenmode = 0, num, den; unsigned transparency = 0; unsigned masking = 0; // no mask uint8_t fmt[16]; int fmt_size; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; avio_skip(pb, 8); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = avio_rl32(pb); iff->bitmap_compression = -1; iff->svx8_compression = -1; iff->maud_bits = -1; iff->maud_compression = -1; while(!url_feof(pb)) { uint64_t orig_pos; int res; const char *metadata_tag = NULL; chunk_id = avio_rl32(pb); data_size = avio_rb32(pb); orig_pos = avio_tell(pb); switch(chunk_id) { case ID_VHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 14) return AVERROR_INVALIDDATA; avio_skip(pb, 12); st->codec->sample_rate = avio_rb16(pb); if (data_size >= 16) { avio_skip(pb, 1); iff->svx8_compression = avio_r8(pb); } break; case ID_MHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 32) return AVERROR_INVALIDDATA; avio_skip(pb, 4); iff->maud_bits = avio_rb16(pb); avio_skip(pb, 2); num = avio_rb32(pb); den = avio_rb16(pb); if (!den) return AVERROR_INVALIDDATA; avio_skip(pb, 2); st->codec->sample_rate = num / den; st->codec->channels = avio_rb16(pb); iff->maud_compression = avio_rb16(pb); if (st->codec->channels == 1) st->codec->channel_layout = AV_CH_LAYOUT_MONO; else if (st->codec->channels == 2) st->codec->channel_layout = AV_CH_LAYOUT_STEREO; break; case ID_ABIT: case ID_BODY: case ID_DBOD: case ID_MDAT: iff->body_pos = avio_tell(pb); iff->body_end = iff->body_pos + data_size; iff->body_size = data_size; break; case ID_CHAN: if (data_size < 4) return AVERROR_INVALIDDATA; if (avio_rb32(pb) < 6) { st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; } else { st->codec->channels = 2; st->codec->channel_layout = AV_CH_LAYOUT_STEREO; } break; case ID_CAMG: if (data_size < 4) return AVERROR_INVALIDDATA; screenmode = avio_rb32(pb); break; case ID_CMAP: if (data_size > INT_MAX - IFF_EXTRA_VIDEO_SIZE - FF_INPUT_BUFFER_PADDING_SIZE) return AVERROR_INVALIDDATA; st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE; st->codec->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0) return AVERROR(EIO); break; case ID_BMHD: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size <= 8) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); avio_skip(pb, 4); // x, y offset st->codec->bits_per_coded_sample = avio_r8(pb); if (data_size >= 10) masking = avio_r8(pb); if (data_size >= 11) iff->bitmap_compression = avio_r8(pb); if (data_size >= 14) { avio_skip(pb, 1); // padding transparency = avio_rb16(pb); } if (data_size >= 16) { st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); } break; case ID_DPEL: if (data_size < 4 || (data_size & 3)) return AVERROR_INVALIDDATA; if ((fmt_size = avio_read(pb, fmt, sizeof(fmt))) < 0) return fmt_size; if (fmt_size == sizeof(deep_rgb24) && !memcmp(fmt, deep_rgb24, sizeof(deep_rgb24))) st->codec->pix_fmt = AV_PIX_FMT_RGB24; else if (fmt_size == sizeof(deep_rgba) && !memcmp(fmt, deep_rgba, sizeof(deep_rgba))) st->codec->pix_fmt = AV_PIX_FMT_RGBA; else if (fmt_size == sizeof(deep_bgra) && !memcmp(fmt, deep_bgra, sizeof(deep_bgra))) st->codec->pix_fmt = AV_PIX_FMT_BGRA; else if (fmt_size == sizeof(deep_argb) && !memcmp(fmt, deep_argb, sizeof(deep_argb))) st->codec->pix_fmt = AV_PIX_FMT_ARGB; else if (fmt_size == sizeof(deep_abgr) && !memcmp(fmt, deep_abgr, sizeof(deep_abgr))) st->codec->pix_fmt = AV_PIX_FMT_ABGR; else { av_log_ask_for_sample(s, "unsupported color format\n"); return AVERROR_PATCHWELCOME; } break; case ID_DGBL: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size < 8) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); iff->bitmap_compression = avio_rb16(pb); st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); st->codec->bits_per_coded_sample = 24; break; case ID_DLOC: if (data_size < 4) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); break; case ID_TVDC: if (data_size < sizeof(iff->tvdc)) return AVERROR_INVALIDDATA; res = avio_read(pb, iff->tvdc, sizeof(iff->tvdc)); if (res < 0) return res; break; case ID_ANNO: case ID_TEXT: metadata_tag = "comment"; break; case ID_AUTH: metadata_tag = "artist"; break; case ID_COPYRIGHT: metadata_tag = "copyright"; break; case ID_NAME: metadata_tag = "title"; break; } if (metadata_tag) { if ((res = get_metadata(s, metadata_tag, data_size)) < 0) { av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", metadata_tag); return res; } } avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1)); } avio_seek(pb, iff->body_pos, SEEK_SET); switch(st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate); if (st->codec->codec_tag == ID_16SV) st->codec->codec_id = AV_CODEC_ID_PCM_S16BE_PLANAR; else if (st->codec->codec_tag == ID_MAUD) { if (iff->maud_bits == 8 && !iff->maud_compression) { st->codec->codec_id = AV_CODEC_ID_PCM_U8; } else if (iff->maud_bits == 16 && !iff->maud_compression) { st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; } else if (iff->maud_bits == 8 && iff->maud_compression == 2) { st->codec->codec_id = AV_CODEC_ID_PCM_ALAW; } else if (iff->maud_bits == 8 && iff->maud_compression == 3) { st->codec->codec_id = AV_CODEC_ID_PCM_MULAW; } else { av_log_ask_for_sample(s, "unsupported compression %d and bit depth %d\n", iff->maud_compression, iff->maud_bits); return AVERROR_PATCHWELCOME; } st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id); st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8; } else { switch (iff->svx8_compression) { case COMP_NONE: st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; break; case COMP_FIB: st->codec->codec_id = AV_CODEC_ID_8SVX_FIB; break; case COMP_EXP: st->codec->codec_id = AV_CODEC_ID_8SVX_EXP; break; default: av_log(s, AV_LOG_ERROR, "Unknown SVX8 compression method '%d'\n", iff->svx8_compression); return -1; } } st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id); st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; break; case AVMEDIA_TYPE_VIDEO: iff->bpp = st->codec->bits_per_coded_sample; if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) { iff->ham = iff->bpp > 6 ? 6 : 4; st->codec->bits_per_coded_sample = 24; } iff->flags = (screenmode & 0x80 /* Extra HalfBrite */) && iff->bpp <= 8; iff->masking = masking; iff->transparency = transparency; if (!st->codec->extradata) { st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE; st->codec->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); } av_assert0(st->codec->extradata_size >= IFF_EXTRA_VIDEO_SIZE); buf = st->codec->extradata; bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE); bytestream_put_byte(&buf, iff->bitmap_compression); bytestream_put_byte(&buf, iff->bpp); bytestream_put_byte(&buf, iff->ham); bytestream_put_byte(&buf, iff->flags); bytestream_put_be16(&buf, iff->transparency); bytestream_put_byte(&buf, iff->masking); bytestream_put_buffer(&buf, iff->tvdc, sizeof(iff->tvdc)); st->codec->codec_id = AV_CODEC_ID_IFF_ILBM; break; default: return -1; } return 0; }
void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) { RTPMuxContext *s = s1->priv_data; const uint8_t *qtables[4] = { NULL }; int nb_qtables = 0; uint8_t type; uint8_t w, h; uint8_t *p; int off = 0; /* fragment offset of the current JPEG frame */ int len; int i; int default_huffman_tables = 0; s->buf_ptr = s->buf; s->timestamp = s->cur_timestamp; /* convert video pixel dimensions from pixels to blocks */ w = FF_CEIL_RSHIFT(s1->streams[0]->codec->width, 3); h = FF_CEIL_RSHIFT(s1->streams[0]->codec->height, 3); /* get the pixel format type or fail */ if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ422P || (s1->streams[0]->codec->color_range == AVCOL_RANGE_JPEG && s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV422P)) { type = 0; } else if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ420P || (s1->streams[0]->codec->color_range == AVCOL_RANGE_JPEG && s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV420P)) { type = 1; } else { av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n"); return; } /* preparse the header for getting some infos */ for (i = 0; i < size; i++) { if (buf[i] != 0xff) continue; if (buf[i + 1] == DQT) { int tables, j; if (buf[i + 4] & 0xF0) av_log(s1, AV_LOG_WARNING, "Only 8-bit precision is supported.\n"); /* a quantization table is 64 bytes long */ tables = AV_RB16(&buf[i + 2]) / 65; if (i + 5 + tables * 65 > size) { av_log(s1, AV_LOG_ERROR, "Too short JPEG header. Aborted!\n"); return; } if (nb_qtables + tables > 4) { av_log(s1, AV_LOG_ERROR, "Invalid number of quantisation tables\n"); return; } for (j = 0; j < tables; j++) qtables[nb_qtables + j] = buf + i + 5 + j * 65; nb_qtables += tables; } else if (buf[i + 1] == SOF0) { if (buf[i + 14] != 17 || buf[i + 17] != 17) { av_log(s1, AV_LOG_ERROR, "Only 1x1 chroma blocks are supported. Aborted!\n"); return; } } else if (buf[i + 1] == DHT) { int dht_size = AV_RB16(&buf[i + 2]); default_huffman_tables |= 1 << 4; i += 3; dht_size -= 2; if (i + dht_size >= size) continue; while (dht_size > 0) switch (buf[i + 1]) { case 0x00: if ( dht_size >= 29 && !memcmp(buf + i + 2, avpriv_mjpeg_bits_dc_luminance + 1, 16) && !memcmp(buf + i + 18, avpriv_mjpeg_val_dc, 12)) { default_huffman_tables |= 1; i += 29; dht_size -= 29; } else { i += dht_size; dht_size = 0; } break; case 0x01: if ( dht_size >= 29 && !memcmp(buf + i + 2, avpriv_mjpeg_bits_dc_chrominance + 1, 16) && !memcmp(buf + i + 18, avpriv_mjpeg_val_dc, 12)) { default_huffman_tables |= 1 << 1; i += 29; dht_size -= 29; } else { i += dht_size; dht_size = 0; } break; case 0x10: if ( dht_size >= 179 && !memcmp(buf + i + 2, avpriv_mjpeg_bits_ac_luminance + 1, 16) && !memcmp(buf + i + 18, avpriv_mjpeg_val_ac_luminance, 162)) { default_huffman_tables |= 1 << 2; i += 179; dht_size -= 179; } else { i += dht_size; dht_size = 0; } break; case 0x11: if ( dht_size >= 179 && !memcmp(buf + i + 2, avpriv_mjpeg_bits_ac_chrominance + 1, 16) && !memcmp(buf + i + 18, avpriv_mjpeg_val_ac_chrominance, 162)) { default_huffman_tables |= 1 << 3; i += 179; dht_size -= 179; } else { i += dht_size; dht_size = 0; } break; default: i += dht_size; dht_size = 0; continue; } } else if (buf[i + 1] == SOS) { /* SOS is last marker in the header */ i += AV_RB16(&buf[i + 2]) + 2; if (i > size) { av_log(s1, AV_LOG_ERROR, "Insufficient data. Aborted!\n"); return; } break; } } if (default_huffman_tables && default_huffman_tables != 31) { av_log(s1, AV_LOG_ERROR, "RFC 2435 requires standard Huffman tables for jpeg\n"); return; } if (nb_qtables && nb_qtables != 2) av_log(s1, AV_LOG_WARNING, "RFC 2435 suggests two quantization tables, %d provided\n", nb_qtables); /* skip JPEG header */ buf += i; size -= i; for (i = size - 2; i >= 0; i--) { if (buf[i] == 0xff && buf[i + 1] == EOI) { /* Remove the EOI marker */ size = i; break; } } p = s->buf_ptr; while (size > 0) { int hdr_size = 8; if (off == 0 && nb_qtables) hdr_size += 4 + 64 * nb_qtables; /* payload max in one packet */ len = FFMIN(size, s->max_payload_size - hdr_size); /* set main header */ bytestream_put_byte(&p, 0); bytestream_put_be24(&p, off); bytestream_put_byte(&p, type); bytestream_put_byte(&p, 255); bytestream_put_byte(&p, w); bytestream_put_byte(&p, h); if (off == 0 && nb_qtables) { /* set quantization tables header */ bytestream_put_byte(&p, 0); bytestream_put_byte(&p, 0); bytestream_put_be16(&p, 64 * nb_qtables); for (i = 0; i < nb_qtables; i++) bytestream_put_buffer(&p, qtables[i], 64); } /* copy payload data */ memcpy(p, buf, len); /* marker bit is last packet in frame */ ff_rtp_send_data(s1, s->buf, len + hdr_size, size == len); buf += len; size -= len; off += len; p = s->buf; } }
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data) { SgiContext *s = avctx->priv_data; AVFrame * const p = &s->picture; uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf; int x, y, z, length, tablesize; unsigned int width, height, depth, dimension; unsigned char *orig_buf = buf, *end_buf = buf + buf_size; *p = *(AVFrame*)data; p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; width = avctx->width; height = avctx->height; switch (avctx->pix_fmt) { case PIX_FMT_GRAY8: dimension = SGI_SINGLE_CHAN; depth = SGI_GRAYSCALE; break; case PIX_FMT_RGB24: dimension = SGI_MULTI_CHAN; depth = SGI_RGB; break; case PIX_FMT_RGBA: dimension = SGI_MULTI_CHAN; depth = SGI_RGBA; break; default: return AVERROR_INVALIDDATA; } tablesize = depth * height * 4; length = tablesize * 2 + SGI_HEADER_SIZE; if (buf_size < length) { av_log(avctx, AV_LOG_ERROR, "buf_size too small(need %d, got %d)\n", length, buf_size); return -1; } /* Encode header. */ bytestream_put_be16(&buf, SGI_MAGIC); bytestream_put_byte(&buf, avctx->coder_type != FF_CODER_TYPE_RAW); /* RLE 1 - VERBATIM 0*/ bytestream_put_byte(&buf, 1); /* bytes_per_channel */ bytestream_put_be16(&buf, dimension); bytestream_put_be16(&buf, width); bytestream_put_be16(&buf, height); bytestream_put_be16(&buf, depth); /* The rest are constant in this implementation. */ bytestream_put_be32(&buf, 0L); /* pixmin */ bytestream_put_be32(&buf, 255L); /* pixmax */ bytestream_put_be32(&buf, 0L); /* dummy */ /* name */ memset(buf, 0, SGI_HEADER_SIZE); buf += 80; /* colormap */ bytestream_put_be32(&buf, 0L); /* The rest of the 512 byte header is unused. */ buf += 404; offsettab = buf; if (avctx->coder_type != FF_CODER_TYPE_RAW) { /* Skip RLE offset table. */ buf += tablesize; lengthtab = buf; /* Skip RLE length table. */ buf += tablesize; /* Make an intermediate consecutive buffer. */ if (!(encode_buf = av_malloc(width))) return -1; for (z = 0; z < depth; z++) { in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; for (y = 0; y < height; y++) { bytestream_put_be32(&offsettab, buf - orig_buf); for (x = 0; x < width; x++) encode_buf[x] = in_buf[depth * x]; if ((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) { av_free(encode_buf); return -1; } buf += length; bytestream_put_byte(&buf, 0); bytestream_put_be32(&lengthtab, length + 1); in_buf -= p->linesize[0]; } } av_free(encode_buf); } else { for (z = 0; z < depth; z++) { in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; for (y = 0; y < height; y++) { for (x = 0; x < width * depth; x += depth) bytestream_put_byte(&buf, in_buf[x]); in_buf -= p->linesize[0]; } } } /* total length */ return buf - orig_buf; }
static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf, int buf_size, int block_width, int block_height, uint8_t *previous_frame, int *I_frame) { PutBitContext pb; int h_blocks, v_blocks, h_part, v_part, i, j; int buf_pos, res; int pred_blocks = 0; init_put_bits(&pb, buf, buf_size * 8); put_bits(&pb, 4, block_width / 16 - 1); put_bits(&pb, 12, s->image_width); put_bits(&pb, 4, block_height / 16 - 1); put_bits(&pb, 12, s->image_height); flush_put_bits(&pb); buf_pos = 4; h_blocks = s->image_width / block_width; h_part = s->image_width % block_width; v_blocks = s->image_height / block_height; v_part = s->image_height % block_height; /* loop over all block columns */ for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) { int y_pos = j * block_height; // vertical position in frame int cur_blk_height = (j < v_blocks) ? block_height : v_part; /* loop over all block rows */ for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) { int x_pos = i * block_width; // horizontal position in frame int cur_blk_width = (i < h_blocks) ? block_width : h_part; int ret = Z_OK; uint8_t *ptr = buf + buf_pos; /* copy the block to the temp buffer before compression * (if it differs from the previous frame's block) */ res = copy_region_enc(p->data[0], s->tmpblock, s->image_height - (y_pos + cur_blk_height + 1), x_pos, cur_blk_height, cur_blk_width, p->linesize[0], previous_frame); if (res || *I_frame) { unsigned long zsize = 3 * block_width * block_height; ret = compress2(ptr + 2, &zsize, s->tmpblock, 3 * cur_blk_width * cur_blk_height, 9); //ret = deflateReset(&s->zstream); if (ret != Z_OK) av_log(s->avctx, AV_LOG_ERROR, "error while compressing block %dx%d\n", i, j); bytestream_put_be16(&ptr, zsize); buf_pos += zsize + 2; av_dlog(s->avctx, "buf_pos = %d\n", buf_pos); } else { pred_blocks++; bytestream_put_be16(&ptr, 0); buf_pos += 2; } } } if (pred_blocks) *I_frame = 0; else *I_frame = 1; return buf_pos; }
static int iff_read_header(AVFormatContext *s, AVFormatParameters *ap) { IffDemuxContext *iff = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; uint8_t *buf; uint32_t chunk_id, data_size; uint32_t screenmode = 0; unsigned transparency = 0; unsigned masking = 0; // no mask st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->channels = 1; avio_skip(pb, 8); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = avio_rl32(pb); while(!url_feof(pb)) { uint64_t orig_pos; int res; const char *metadata_tag = NULL; chunk_id = avio_rl32(pb); data_size = avio_rb32(pb); orig_pos = avio_tell(pb); switch(chunk_id) { case ID_VHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 14) return AVERROR_INVALIDDATA; avio_skip(pb, 12); st->codec->sample_rate = avio_rb16(pb); if (data_size >= 16) { avio_skip(pb, 1); iff->svx8_compression = avio_r8(pb); } break; case ID_ABIT: case ID_BODY: iff->body_pos = avio_tell(pb); iff->body_size = data_size; break; case ID_CHAN: if (data_size < 4) return AVERROR_INVALIDDATA; st->codec->channels = (avio_rb32(pb) < 6) ? 1 : 2; break; case ID_CAMG: if (data_size < 4) return AVERROR_INVALIDDATA; screenmode = avio_rb32(pb); break; case ID_CMAP: st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE; st->codec->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0) return AVERROR(EIO); break; case ID_BMHD: iff->bitmap_compression = -1; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size <= 8) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); avio_skip(pb, 4); // x, y offset st->codec->bits_per_coded_sample = avio_r8(pb); if (data_size >= 10) masking = avio_r8(pb); if (data_size >= 11) iff->bitmap_compression = avio_r8(pb); if (data_size >= 14) { avio_skip(pb, 1); // padding transparency = avio_rb16(pb); } if (data_size >= 16) { st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); } break; case ID_ANNO: case ID_TEXT: metadata_tag = "comment"; break; case ID_AUTH: metadata_tag = "artist"; break; case ID_COPYRIGHT: metadata_tag = "copyright"; break; case ID_NAME: metadata_tag = "title"; break; } if (metadata_tag) { if ((res = get_metadata(s, metadata_tag, data_size)) < 0) { av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!", metadata_tag); return res; } } avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1)); } avio_seek(pb, iff->body_pos, SEEK_SET); switch(st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate); switch (iff->svx8_compression) { case COMP_NONE: st->codec->codec_id = CODEC_ID_PCM_S8_PLANAR; break; case COMP_FIB: st->codec->codec_id = CODEC_ID_8SVX_FIB; break; case COMP_EXP: st->codec->codec_id = CODEC_ID_8SVX_EXP; break; default: av_log(s, AV_LOG_ERROR, "Unknown SVX8 compression method '%d'\n", iff->svx8_compression); return -1; } st->codec->bits_per_coded_sample = iff->svx8_compression == COMP_NONE ? 8 : 4; st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; break; case AVMEDIA_TYPE_VIDEO: iff->bpp = st->codec->bits_per_coded_sample; if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) { iff->ham = iff->bpp > 6 ? 6 : 4; st->codec->bits_per_coded_sample = 24; } iff->flags = (screenmode & 0x80 /* Extra HalfBrite */) && iff->bpp <= 8; iff->masking = masking; iff->transparency = transparency; if (!st->codec->extradata) { st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE; st->codec->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); } buf = st->codec->extradata; bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE); bytestream_put_byte(&buf, iff->bitmap_compression); bytestream_put_byte(&buf, iff->bpp); bytestream_put_byte(&buf, iff->ham); bytestream_put_byte(&buf, iff->flags); bytestream_put_be16(&buf, iff->transparency); bytestream_put_byte(&buf, iff->masking); switch (iff->bitmap_compression) { case BITMAP_RAW: st->codec->codec_id = CODEC_ID_IFF_ILBM; break; case BITMAP_BYTERUN1: st->codec->codec_id = CODEC_ID_IFF_BYTERUN1; break; default: av_log(s, AV_LOG_ERROR, "Unknown bitmap compression method '%d'\n", iff->bitmap_compression); return AVERROR_INVALIDDATA; } break; default: return -1; } return 0; }
void ff_amf_write_field_name(uint8_t **dst, const char *str) { bytestream_put_be16(dst, strlen(str)); bytestream_put_buffer(dst, str, strlen(str)); }
void ff_amf_write_string(uint8_t **dst, const char *str) { bytestream_put_byte(dst, AMF_DATA_TYPE_STRING); bytestream_put_be16(dst, strlen(str)); bytestream_put_buffer(dst, str, strlen(str)); }
static int iff_read_header(AVFormatContext *s) { IffDemuxContext *iff = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; uint8_t *buf; uint32_t chunk_id; uint64_t data_size; uint32_t screenmode = 0, num, den; unsigned transparency = 0; unsigned masking = 0; // no mask uint8_t fmt[16]; int fmt_size; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; iff->is_64bit = avio_rl32(pb) == ID_FRM8; avio_skip(pb, iff->is_64bit ? 8 : 4); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = avio_rl32(pb); if (st->codec->codec_tag == ID_ANIM) { avio_skip(pb, 8); st->codec->codec_tag = avio_rl32(pb); } iff->bitmap_compression = -1; iff->svx8_compression = -1; iff->maud_bits = -1; iff->maud_compression = -1; while(!avio_feof(pb)) { uint64_t orig_pos; int res; const char *metadata_tag = NULL; int version, nb_comments, i; chunk_id = avio_rl32(pb); data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb); orig_pos = avio_tell(pb); switch(chunk_id) { case ID_VHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 14) return AVERROR_INVALIDDATA; avio_skip(pb, 12); st->codec->sample_rate = avio_rb16(pb); if (data_size >= 16) { avio_skip(pb, 1); iff->svx8_compression = avio_r8(pb); } break; case ID_MHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 32) return AVERROR_INVALIDDATA; avio_skip(pb, 4); iff->maud_bits = avio_rb16(pb); avio_skip(pb, 2); num = avio_rb32(pb); den = avio_rb16(pb); if (!den) return AVERROR_INVALIDDATA; avio_skip(pb, 2); st->codec->sample_rate = num / den; st->codec->channels = avio_rb16(pb); iff->maud_compression = avio_rb16(pb); if (st->codec->channels == 1) st->codec->channel_layout = AV_CH_LAYOUT_MONO; else if (st->codec->channels == 2) st->codec->channel_layout = AV_CH_LAYOUT_STEREO; break; case ID_ABIT: case ID_BODY: case ID_DBOD: case ID_DSD: case ID_MDAT: iff->body_pos = avio_tell(pb); iff->body_end = iff->body_pos + data_size; iff->body_size = data_size; break; case ID_CHAN: if (data_size < 4) return AVERROR_INVALIDDATA; if (avio_rb32(pb) < 6) { st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; } else { st->codec->channels = 2; st->codec->channel_layout = AV_CH_LAYOUT_STEREO; } break; case ID_CAMG: if (data_size < 4) return AVERROR_INVALIDDATA; screenmode = avio_rb32(pb); break; case ID_CMAP: if (data_size < 3 || data_size > 768 || data_size % 3) { av_log(s, AV_LOG_ERROR, "Invalid CMAP chunk size %"PRIu64"\n", data_size); return AVERROR_INVALIDDATA; } st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE; st->codec->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0) return AVERROR(EIO); break; case ID_BMHD: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size <= 8) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); avio_skip(pb, 4); // x, y offset st->codec->bits_per_coded_sample = avio_r8(pb); if (data_size >= 10) masking = avio_r8(pb); if (data_size >= 11) iff->bitmap_compression = avio_r8(pb); if (data_size >= 14) { avio_skip(pb, 1); // padding transparency = avio_rb16(pb); } if (data_size >= 16) { st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); } break; case ID_DPEL: if (data_size < 4 || (data_size & 3)) return AVERROR_INVALIDDATA; if ((fmt_size = avio_read(pb, fmt, sizeof(fmt))) < 0) return fmt_size; if (fmt_size == sizeof(deep_rgb24) && !memcmp(fmt, deep_rgb24, sizeof(deep_rgb24))) st->codec->pix_fmt = AV_PIX_FMT_RGB24; else if (fmt_size == sizeof(deep_rgba) && !memcmp(fmt, deep_rgba, sizeof(deep_rgba))) st->codec->pix_fmt = AV_PIX_FMT_RGBA; else if (fmt_size == sizeof(deep_bgra) && !memcmp(fmt, deep_bgra, sizeof(deep_bgra))) st->codec->pix_fmt = AV_PIX_FMT_BGRA; else if (fmt_size == sizeof(deep_argb) && !memcmp(fmt, deep_argb, sizeof(deep_argb))) st->codec->pix_fmt = AV_PIX_FMT_ARGB; else if (fmt_size == sizeof(deep_abgr) && !memcmp(fmt, deep_abgr, sizeof(deep_abgr))) st->codec->pix_fmt = AV_PIX_FMT_ABGR; else { avpriv_request_sample(s, "color format %.16s", fmt); return AVERROR_PATCHWELCOME; } break; case ID_DGBL: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size < 8) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); iff->bitmap_compression = avio_rb16(pb); st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); st->codec->bits_per_coded_sample = 24; break; case ID_DLOC: if (data_size < 4) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); break; case ID_TVDC: if (data_size < sizeof(iff->tvdc)) return AVERROR_INVALIDDATA; res = avio_read(pb, iff->tvdc, sizeof(iff->tvdc)); if (res < 0) return res; break; case ID_ANNO: case ID_TEXT: metadata_tag = "comment"; break; case ID_AUTH: metadata_tag = "artist"; break; case ID_COPYRIGHT: metadata_tag = "copyright"; break; case ID_NAME: metadata_tag = "title"; break; /* DSD tags */ case MKTAG('F','V','E','R'): if (data_size < 4) return AVERROR_INVALIDDATA; version = avio_rb32(pb); av_log(s, AV_LOG_DEBUG, "DSIFF v%d.%d.%d.%d\n",version >> 24, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; break; case MKTAG('D','I','I','N'): res = parse_dsd_diin(s, st, orig_pos + data_size); if (res < 0) return res; break; case MKTAG('P','R','O','P'): if (data_size < 4) return AVERROR_INVALIDDATA; if (avio_rl32(pb) != MKTAG('S','N','D',' ')) { avpriv_request_sample(s, "unknown property type"); break; } res = parse_dsd_prop(s, st, orig_pos + data_size); if (res < 0) return res; break; case MKTAG('C','O','M','T'): if (data_size < 2) return AVERROR_INVALIDDATA; nb_comments = avio_rb16(pb); for (i = 0; i < nb_comments; i++) { int year, mon, day, hour, min, type, ref; char tmp[24]; const char *tag; int metadata_size; year = avio_rb16(pb); mon = avio_r8(pb); day = avio_r8(pb); hour = avio_r8(pb); min = avio_r8(pb); snprintf(tmp, sizeof(tmp), "%04d-%02d-%02d %02d:%02d", year, mon, day, hour, min); av_dict_set(&st->metadata, "comment_time", tmp, 0); type = avio_rb16(pb); ref = avio_rb16(pb); switch (type) { case 1: if (!i) tag = "channel_comment"; else { snprintf(tmp, sizeof(tmp), "channel%d_comment", ref); tag = tmp; } break; case 2: tag = ref < FF_ARRAY_ELEMS(dsd_source_comment) ? dsd_source_comment[ref] : "source_comment"; break; case 3: tag = ref < FF_ARRAY_ELEMS(dsd_history_comment) ? dsd_history_comment[ref] : "file_history"; break; default: tag = "comment"; } metadata_size = avio_rb32(pb); if ((res = get_metadata(s, tag, metadata_size)) < 0) { av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", tag); return res; } if (metadata_size & 1) avio_skip(pb, 1); } break; } if (metadata_tag) { if ((res = get_metadata(s, metadata_tag, data_size)) < 0) { av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", metadata_tag); return res; } } avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1)); } avio_seek(pb, iff->body_pos, SEEK_SET); switch(st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate); if (st->codec->codec_tag == ID_16SV) st->codec->codec_id = AV_CODEC_ID_PCM_S16BE_PLANAR; else if (st->codec->codec_tag == ID_MAUD) { if (iff->maud_bits == 8 && !iff->maud_compression) { st->codec->codec_id = AV_CODEC_ID_PCM_U8; } else if (iff->maud_bits == 16 && !iff->maud_compression) { st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; } else if (iff->maud_bits == 8 && iff->maud_compression == 2) { st->codec->codec_id = AV_CODEC_ID_PCM_ALAW; } else if (iff->maud_bits == 8 && iff->maud_compression == 3) { st->codec->codec_id = AV_CODEC_ID_PCM_MULAW; } else { avpriv_request_sample(s, "compression %d and bit depth %d", iff->maud_compression, iff->maud_bits); return AVERROR_PATCHWELCOME; } } else if (st->codec->codec_tag != ID_DSD) { switch (iff->svx8_compression) { case COMP_NONE: st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; break; case COMP_FIB: st->codec->codec_id = AV_CODEC_ID_8SVX_FIB; break; case COMP_EXP: st->codec->codec_id = AV_CODEC_ID_8SVX_EXP; break; default: av_log(s, AV_LOG_ERROR, "Unknown SVX8 compression method '%d'\n", iff->svx8_compression); return -1; } } st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id); st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; break; case AVMEDIA_TYPE_VIDEO: iff->bpp = st->codec->bits_per_coded_sample; if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) { iff->ham = iff->bpp > 6 ? 6 : 4; st->codec->bits_per_coded_sample = 24; } iff->flags = (screenmode & 0x80 /* Extra HalfBrite */) && iff->bpp <= 8; iff->masking = masking; iff->transparency = transparency; if (!st->codec->extradata) { st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE; st->codec->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); } av_assert0(st->codec->extradata_size >= IFF_EXTRA_VIDEO_SIZE); buf = st->codec->extradata; bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE); bytestream_put_byte(&buf, iff->bitmap_compression); bytestream_put_byte(&buf, iff->bpp); bytestream_put_byte(&buf, iff->ham); bytestream_put_byte(&buf, iff->flags); bytestream_put_be16(&buf, iff->transparency); bytestream_put_byte(&buf, iff->masking); bytestream_put_buffer(&buf, iff->tvdc, sizeof(iff->tvdc)); st->codec->codec_id = AV_CODEC_ID_IFF_ILBM; break; default: return -1; } return 0; }
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { SgiContext *s = avctx->priv_data; AVFrame * const p = &s->picture; uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf, *buf; int x, y, z, length, tablesize, ret; unsigned int width, height, depth, dimension, bytes_per_channel, pixmax, put_be; unsigned char *end_buf; *p = *frame; p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; width = avctx->width; height = avctx->height; bytes_per_channel = 1; pixmax = 0xFF; put_be = HAVE_BIGENDIAN; switch (avctx->pix_fmt) { case PIX_FMT_GRAY8: dimension = SGI_SINGLE_CHAN; depth = SGI_GRAYSCALE; break; case PIX_FMT_RGB24: dimension = SGI_MULTI_CHAN; depth = SGI_RGB; break; case PIX_FMT_RGBA: dimension = SGI_MULTI_CHAN; depth = SGI_RGBA; break; case PIX_FMT_GRAY16LE: put_be = !HAVE_BIGENDIAN; case PIX_FMT_GRAY16BE: avctx->coder_type = FF_CODER_TYPE_RAW; bytes_per_channel = 2; pixmax = 0xFFFF; dimension = SGI_SINGLE_CHAN; depth = SGI_GRAYSCALE; break; case PIX_FMT_RGB48LE: put_be = !HAVE_BIGENDIAN; case PIX_FMT_RGB48BE: avctx->coder_type = FF_CODER_TYPE_RAW; bytes_per_channel = 2; pixmax = 0xFFFF; dimension = SGI_MULTI_CHAN; depth = SGI_RGB; break; case PIX_FMT_RGBA64LE: put_be = !HAVE_BIGENDIAN; case PIX_FMT_RGBA64BE: avctx->coder_type = FF_CODER_TYPE_RAW; bytes_per_channel = 2; pixmax = 0xFFFF; dimension = SGI_MULTI_CHAN; depth = SGI_RGBA; break; default: return AVERROR_INVALIDDATA; } tablesize = depth * height * 4; length = SGI_HEADER_SIZE; if (avctx->coder_type == FF_CODER_TYPE_RAW) length += depth * height * width; else // assume ff_rl_encode() produces at most 2x size of input length += tablesize * 2 + depth * height * (2 * width + 1); if ((ret = ff_alloc_packet2(avctx, pkt, bytes_per_channel * length)) < 0) return ret; buf = pkt->data; end_buf = pkt->data + pkt->size; /* Encode header. */ bytestream_put_be16(&buf, SGI_MAGIC); bytestream_put_byte(&buf, avctx->coder_type != FF_CODER_TYPE_RAW); /* RLE 1 - VERBATIM 0*/ bytestream_put_byte(&buf, bytes_per_channel); bytestream_put_be16(&buf, dimension); bytestream_put_be16(&buf, width); bytestream_put_be16(&buf, height); bytestream_put_be16(&buf, depth); bytestream_put_be32(&buf, 0L); /* pixmin */ bytestream_put_be32(&buf, pixmax); bytestream_put_be32(&buf, 0L); /* dummy */ /* name */ memset(buf, 0, SGI_HEADER_SIZE); buf += 80; /* colormap */ bytestream_put_be32(&buf, 0L); /* The rest of the 512 byte header is unused. */ buf += 404; offsettab = buf; if (avctx->coder_type != FF_CODER_TYPE_RAW) { /* Skip RLE offset table. */ buf += tablesize; lengthtab = buf; /* Skip RLE length table. */ buf += tablesize; /* Make an intermediate consecutive buffer. */ if (!(encode_buf = av_malloc(width))) return -1; for (z = 0; z < depth; z++) { in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; for (y = 0; y < height; y++) { bytestream_put_be32(&offsettab, buf - pkt->data); for (x = 0; x < width; x++) encode_buf[x] = in_buf[depth * x]; if ((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) { av_free(encode_buf); return -1; } buf += length; bytestream_put_byte(&buf, 0); bytestream_put_be32(&lengthtab, length + 1); in_buf -= p->linesize[0]; } } av_free(encode_buf); } else { for (z = 0; z < depth; z++) { in_buf = p->data[0] + p->linesize[0] * (height - 1) + z * bytes_per_channel; for (y = 0; y < height; y++) { for (x = 0; x < width * depth; x += depth) if (bytes_per_channel == 1) { bytestream_put_byte(&buf, in_buf[x]); } else { if (put_be) { bytestream_put_be16(&buf, ((uint16_t *)in_buf)[x]); } else { bytestream_put_le16(&buf, ((uint16_t *)in_buf)[x]); } } in_buf -= p->linesize[0]; } } } /* total length */ pkt->size = buf - pkt->data; pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; }
void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) { RTPMuxContext *s = s1->priv_data; const uint8_t *qtables = NULL; int nb_qtables = 0; uint8_t type; uint8_t w, h; uint8_t *p; int off = 0; /* fragment offset of the current JPEG frame */ int len; int i; s->buf_ptr = s->buf; s->timestamp = s->cur_timestamp; /* convert video pixel dimensions from pixels to blocks */ w = FF_CEIL_RSHIFT(s1->streams[0]->codec->width, 3); h = FF_CEIL_RSHIFT(s1->streams[0]->codec->height, 3); /* get the pixel format type or fail */ if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ422P || (s1->streams[0]->codec->color_range == AVCOL_RANGE_JPEG && s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV422P)) { type = 0; } else if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ420P || (s1->streams[0]->codec->color_range == AVCOL_RANGE_JPEG && s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV420P)) { type = 1; } else { av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n"); return; } /* preparse the header for getting some infos */ for (i = 0; i < size; i++) { if (buf[i] != 0xff) continue; if (buf[i + 1] == DQT) { if (buf[i + 4]) av_log(s1, AV_LOG_WARNING, "Only 8-bit precision is supported.\n"); /* a quantization table is 64 bytes long */ nb_qtables = AV_RB16(&buf[i + 2]) / 65; if (i + 4 + nb_qtables * 65 > size) { av_log(s1, AV_LOG_ERROR, "Too short JPEG header. Aborted!\n"); return; } qtables = &buf[i + 4]; } else if (buf[i + 1] == SOF0) { if (buf[i + 14] != 17 || buf[i + 17] != 17) { av_log(s1, AV_LOG_ERROR, "Only 1x1 chroma blocks are supported. Aborted!\n"); return; } } else if (buf[i + 1] == SOS) { /* SOS is last marker in the header */ i += AV_RB16(&buf[i + 2]) + 2; if (i > size) { av_log(s1, AV_LOG_ERROR, "Insufficient data. Aborted!\n"); return; } break; } } /* skip JPEG header */ buf += i; size -= i; for (i = size - 2; i >= 0; i--) { if (buf[i] == 0xff && buf[i + 1] == EOI) { /* Remove the EOI marker */ size = i; break; } } p = s->buf_ptr; while (size > 0) { int hdr_size = 8; if (off == 0 && nb_qtables) hdr_size += 4 + 64 * nb_qtables; /* payload max in one packet */ len = FFMIN(size, s->max_payload_size - hdr_size); /* set main header */ bytestream_put_byte(&p, 0); bytestream_put_be24(&p, off); bytestream_put_byte(&p, type); bytestream_put_byte(&p, 255); bytestream_put_byte(&p, w); bytestream_put_byte(&p, h); if (off == 0 && nb_qtables) { /* set quantization tables header */ bytestream_put_byte(&p, 0); bytestream_put_byte(&p, 0); bytestream_put_be16(&p, 64 * nb_qtables); for (i = 0; i < nb_qtables; i++) bytestream_put_buffer(&p, &qtables[65 * i + 1], 64); } /* copy payload data */ memcpy(p, buf, len); /* marker bit is last packet in frame */ ff_rtp_send_data(s1, s->buf, len + hdr_size, size == len); buf += len; size -= len; off += len; p = s->buf; } }