int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) { if (len > 6) { /* check for h264 start code */ if (AV_RB32(data) == 0x00000001 || AV_RB24(data) == 0x000001) { uint8_t *buf=NULL, *end, *start; uint32_t sps_size=0, pps_size=0; uint8_t *sps=0, *pps=0; int ret = ff_avc_parse_nal_units_buf(data, &buf, &len); if (ret < 0) return ret; start = buf; end = buf + len; /* look for sps and pps */ while (buf < end) { unsigned int size; uint8_t nal_type; size = AV_RB32(buf); nal_type = buf[4] & 0x1f; if (nal_type == 7) { /* SPS */ sps = buf + 4; sps_size = size; } else if (nal_type == 8) { /* PPS */ pps = buf + 4; pps_size = size; } buf += size + 4; } assert(sps); assert(pps); avio_w8(pb, 1); /* version */ avio_w8(pb, sps[1]); /* profile */ avio_w8(pb, sps[2]); /* profile compat */ avio_w8(pb, sps[3]); /* level */ avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ avio_wb16(pb, sps_size); avio_write(pb, sps, sps_size); avio_w8(pb, 1); /* number of pps */ avio_wb16(pb, pps_size); avio_write(pb, pps, pps_size); av_free(start); } else { avio_write(pb, data, len); } } return 0; }
static void output_match(AVIOContext *out, int match_sample, int match_offset, int match_len, int *entries) { avio_w8(out, 2); /* sample constructor */ avio_w8(out, 0); /* track reference */ avio_wb16(out, match_len); avio_wb32(out, match_sample); avio_wb32(out, match_offset); avio_wb16(out, 1); /* bytes per block */ avio_wb16(out, 1); /* samples per block */ (*entries)++; }
static int daud_write_packet(struct AVFormatContext *s, AVPacket *pkt) { if (pkt->size > 65535) { av_log(s, AV_LOG_ERROR, "Packet size too large for s302m. (%d > 65535)\n", pkt->size); return -1; } avio_wb16(s->pb, pkt->size); avio_wb16(s->pb, 0x8010); // unknown avio_write(s->pb, pkt->data, pkt->size); return 0; }
static int rso_write_trailer(AVFormatContext *s) { AVIOContext *pb = s->pb; int64_t file_size; uint16_t coded_file_size; file_size = avio_tell(pb); if (file_size < 0) return file_size; if (file_size > 0xffff + RSO_HEADER_SIZE) { av_log(s, AV_LOG_WARNING, "Output file is too big (%"PRId64" bytes >= 64kB)\n", file_size); coded_file_size = 0xffff; } else { coded_file_size = file_size - RSO_HEADER_SIZE; } /* update file size */ avio_seek(pb, 2, SEEK_SET); avio_wb16(pb, coded_file_size); avio_seek(pb, file_size, SEEK_SET); avio_flush(pb); return 0; }
static void put_str(AVIOContext *s, const char *tag) { avio_wb16(s,strlen(tag)); while (*tag) { avio_w8(s, *tag++); } }
int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par) { int profile = par->profile; int level = par->level == FF_LEVEL_UNKNOWN ? 0 : par->level; int bit_depth = get_bit_depth(s, par->format); int vpx_color_space = get_vpx_color_space(s, par->color_space); int vpx_chroma_subsampling = get_vpx_chroma_subsampling(s, par->format, par->chroma_location); int vpx_transfer_function = get_vpx_transfer_function(par->color_trc); int vpx_video_full_range_flag = get_vpx_video_full_range_flag(par->color_range); if (bit_depth < 0 || vpx_color_space < 0 || vpx_chroma_subsampling < 0) return AVERROR_INVALIDDATA; if (profile == FF_PROFILE_UNKNOWN) { if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL || vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) { profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : FF_PROFILE_VP9_2; } else { profile = (bit_depth == 8) ? FF_PROFILE_VP9_1 : FF_PROFILE_VP9_3; } } avio_w8(pb, profile); avio_w8(pb, level); avio_w8(pb, (bit_depth << 4) | vpx_color_space); avio_w8(pb, (vpx_chroma_subsampling << 4) | (vpx_transfer_function << 1) | vpx_video_full_range_flag); // vp9 does not have codec initialization data. avio_wb16(pb, 0); return 0; }
static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags) { RMMuxContext *rm = s->priv_data; AVIOContext *pb = s->pb; StreamInfo *stream = rm->video_stream; int key_frame = !!(flags & AV_PKT_FLAG_KEY); /* XXX: this is incorrect: should be a parameter */ /* Well, I spent some time finding the meaning of these bits. I am not sure I understood everything, but it works !! */ #if 1 if (size > MAX_PACKET_SIZE) { av_log(s, AV_LOG_ERROR, "Muxing packets larger than 64 kB (%d) is not supported\n", size); return AVERROR_PATCHWELCOME; } write_packet_header(s, stream, size + 7 + (size >= 0x4000)*4, key_frame); /* bit 7: '1' if final packet of a frame converted in several packets */ avio_w8(pb, 0x81); /* bit 7: '1' if I frame. bits 6..0 : sequence number in current frame starting from 1 */ if (key_frame) { avio_w8(pb, 0x81); } else { avio_w8(pb, 0x01); } if(size >= 0x4000) { avio_wb32(pb, size); /* total frame size */ avio_wb32(pb, size); /* offset from the start or the end */ } else { avio_wb16(pb, 0x4000 | size); /* total frame size */ avio_wb16(pb, 0x4000 | size); /* offset from the start or the end */ } #else /* full frame */ write_packet_header(s, size + 6); avio_w8(pb, 0xc0); avio_wb16(pb, 0x4000 + size); /* total frame size */ avio_wb16(pb, 0x4000 + packet_number * 126); /* position in stream */ #endif avio_w8(pb, stream->nb_frames & 0xff); avio_write(pb, buf, size); stream->nb_frames++; return 0; }
static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size) { GXFContext *gxf = s->priv_data; AVIOContext *pb = s->pb; AVStream *st = s->streams[pkt->stream_index]; GXFStreamContext *sc = st->priv_data; unsigned field_nb; /* If the video is frame-encoded, the frame numbers shall be represented by * even field numbers. * see SMPTE360M-2004 6.4.2.1.3 Media field number */ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { field_nb = gxf->nb_fields; } else { field_nb = av_rescale_rnd(pkt->dts, gxf->time_base.den, (int64_t)48000*gxf->time_base.num, AV_ROUND_UP); } avio_w8(pb, sc->media_type); avio_w8(pb, st->index); avio_wb32(pb, field_nb); if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { avio_wb16(pb, 0); avio_wb16(pb, size / 2); } else if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) { int frame_type = gxf_parse_mpeg_frame(sc, pkt->data, pkt->size); if (frame_type == AV_PICTURE_TYPE_I) { avio_w8(pb, 0x0d); sc->iframes++; } else if (frame_type == AV_PICTURE_TYPE_B) { avio_w8(pb, 0x0f); sc->bframes++; } else { avio_w8(pb, 0x0e); sc->pframes++; } avio_wb24(pb, size); } else if (st->codec->codec_id == CODEC_ID_DVVIDEO) { avio_w8(pb, size / 4096); avio_wb24(pb, 0); } else avio_wb32(pb, size); avio_wb32(pb, field_nb); avio_w8(pb, 1); /* flags */ avio_w8(pb, 0); /* reserved */ return 16; }
/* send an rtcp sender report packet */ static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time, int bye) { RTPMuxContext *s = s1->priv_data; uint32_t rtp_ts; av_log(s1, AV_LOG_TRACE, "RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp); s->last_rtcp_ntp_time = ntp_time; rtp_ts = av_rescale_q(ntp_time - s->first_rtcp_ntp_time, (AVRational){1, 1000000}, s1->streams[0]->time_base) + s->base_timestamp; avio_w8(s1->pb, RTP_VERSION << 6); avio_w8(s1->pb, RTCP_SR); avio_wb16(s1->pb, 6); /* length in words - 1 */ avio_wb32(s1->pb, s->ssrc); avio_wb32(s1->pb, ntp_time / 1000000); avio_wb32(s1->pb, ((ntp_time % 1000000) << 32) / 1000000); avio_wb32(s1->pb, rtp_ts); avio_wb32(s1->pb, s->packet_count); avio_wb32(s1->pb, s->octet_count); if (s->cname) { int len = FFMIN(strlen(s->cname), 255); avio_w8(s1->pb, (RTP_VERSION << 6) + 1); avio_w8(s1->pb, RTCP_SDES); avio_wb16(s1->pb, (7 + len + 3) / 4); /* length in words - 1 */ avio_wb32(s1->pb, s->ssrc); avio_w8(s1->pb, 0x01); /* CNAME */ avio_w8(s1->pb, len); avio_write(s1->pb, s->cname, len); avio_w8(s1->pb, 0); /* END */ for (len = (7 + len) % 4; len % 4; len++) avio_w8(s1->pb, 0); } if (bye) { avio_w8(s1->pb, (RTP_VERSION << 6) | 1); avio_w8(s1->pb, RTCP_BYE); avio_wb16(s1->pb, 1); /* length in words - 1 */ avio_wb32(s1->pb, s->ssrc); } avio_flush(s1->pb); }
static int64_t updateSize(AVIOContext *pb, int64_t pos) { int64_t curpos; curpos = avio_tell(pb); avio_seek(pb, pos, SEEK_SET); avio_wb16(pb, curpos - pos - 2); avio_seek(pb, curpos, SEEK_SET); return curpos - pos; }
static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream, int length, int key_frame) { int timestamp; AVIOContext *s = ctx->pb; stream->nb_packets++; stream->packet_total_size += length; if (length > stream->packet_max_size) stream->packet_max_size = length; avio_wb16(s,0); /* version */ avio_wb16(s,length + 12); avio_wb16(s, stream->num); /* stream number */ timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate; avio_wb32(s, timestamp); /* timestamp */ avio_w8(s, 0); /* reserved */ avio_w8(s, key_frame ? 2 : 0); /* flags */ }
static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream, int length, int key_frame) { int timestamp; AVIOContext *s = ctx->pb; stream->nb_packets++; stream->packet_total_size += length; if (length > stream->packet_max_size) stream->packet_max_size = length; avio_wb16(s,0); /* version */ avio_wb16(s,length + 12); avio_wb16(s, stream->num); /* stream number */ timestamp = av_rescale_q_rnd(stream->nb_frames, (AVRational){1000, 1}, stream->frame_rate, AV_ROUND_ZERO); avio_wb32(s, timestamp); /* timestamp */ avio_w8(s, 0); /* reserved */ avio_w8(s, key_frame ? 2 : 0); /* flags */ }
static int rso_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; AVCodecParameters *par = s->streams[0]->codecpar; if (!par->codec_tag) return AVERROR_INVALIDDATA; if (par->channels != 1) { av_log(s, AV_LOG_ERROR, "RSO only supports mono\n"); return AVERROR_INVALIDDATA; } if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) { av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n"); return AVERROR_INVALIDDATA; } /* XXX: find legal sample rates (if any) */ if (par->sample_rate >= 1u<<16) { av_log(s, AV_LOG_ERROR, "Sample rate must be < 65536\n"); return AVERROR_INVALIDDATA; } if (par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { avpriv_report_missing_feature(s, "ADPCM in RSO"); return AVERROR_PATCHWELCOME; } /* format header */ avio_wb16(pb, par->codec_tag); /* codec ID */ avio_wb16(pb, 0); /* data size, will be written at EOF */ avio_wb16(pb, par->sample_rate); avio_wb16(pb, 0x0000); /* play mode ? (0x0000 = don't loop) */ avio_flush(pb); return 0; }
static int rso_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; if (!enc->codec_tag) return AVERROR_INVALIDDATA; if (enc->channels != 1) { av_log(s, AV_LOG_ERROR, "RSO only supports mono\n"); return AVERROR_INVALIDDATA; } if (url_is_streamed(s->pb)) { av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n"); return AVERROR_INVALIDDATA; } /* XXX: find legal sample rates (if any) */ if (enc->sample_rate >= 1u<<16) { av_log(s, AV_LOG_ERROR, "Sample rate must be < 65536\n"); return AVERROR_INVALIDDATA; } if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) { av_log(s, AV_LOG_ERROR, "ADPCM in RSO not implemented\n"); return AVERROR_PATCHWELCOME; } /* format header */ avio_wb16(pb, enc->codec_tag); /* codec ID */ avio_wb16(pb, 0); /* data size, will be written at EOF */ avio_wb16(pb, enc->sample_rate); avio_wb16(pb, 0x0000); /* play mode ? (0x0000 = don't loop) */ avio_flush(pb); return 0; }
static int gxf_write_material_data_section(AVFormatContext *s) { GXFContext *gxf = s->priv_data; AVIOContext *pb = s->pb; int64_t pos; int len; const char *filename = strrchr(s->filename, '/'); pos = avio_tell(pb); avio_wb16(pb, 0); /* size */ /* name */ if (filename) filename++; else filename = s->filename; len = strlen(filename); avio_w8(pb, MAT_NAME); avio_w8(pb, strlen(SERVER_PATH) + len + 1); avio_write(pb, SERVER_PATH, sizeof(SERVER_PATH) - 1); avio_write(pb, filename, len); avio_w8(pb, 0); /* first field */ avio_w8(pb, MAT_FIRST_FIELD); avio_w8(pb, 4); avio_wb32(pb, 0); /* last field */ avio_w8(pb, MAT_LAST_FIELD); avio_w8(pb, 4); avio_wb32(pb, gxf->nb_fields); /* reserved */ avio_w8(pb, MAT_MARK_IN); avio_w8(pb, 4); avio_wb32(pb, 0); avio_w8(pb, MAT_MARK_OUT); avio_w8(pb, 4); avio_wb32(pb, gxf->nb_fields); /* estimated size */ avio_w8(pb, MAT_SIZE); avio_w8(pb, 4); avio_wb32(pb, avio_size(pb) / 1024); return updateSize(pb, pos); }
void rtp_send_punch_packets(URLContext* rtp_handle) { AVIOContext *pb; uint8_t *buf; int len; /* Send a small RTP packet */ if (url_open_dyn_buf(&pb) < 0) return; avio_w8(pb, (RTP_VERSION << 6)); avio_w8(pb, 0); /* Payload type */ avio_wb16(pb, 0); /* Seq */ avio_wb32(pb, 0); /* Timestamp */ avio_wb32(pb, 0); /* SSRC */ avio_flush(pb); len = url_close_dyn_buf(pb, &buf); if ((len > 0) && buf) url_write(rtp_handle, buf, len); av_free(buf); /* Send a minimal RTCP RR */ if (url_open_dyn_buf(&pb) < 0) return; avio_w8(pb, (RTP_VERSION << 6)); avio_w8(pb, RTCP_RR); /* receiver report */ avio_wb16(pb, 1); /* length in words - 1 */ avio_wb32(pb, 0); /* our own SSRC */ avio_flush(pb); len = url_close_dyn_buf(pb, &buf); if ((len > 0) && buf) url_write(rtp_handle, buf, len); av_free(buf); }
static int gxf_write_track_description_section(AVFormatContext *s) { GXFContext *gxf = s->priv_data; AVIOContext *pb = s->pb; int64_t pos; int i; pos = avio_tell(pb); avio_wb16(pb, 0); /* size */ for (i = 0; i < s->nb_streams; ++i) gxf_write_track_description(s, s->streams[i]->priv_data, i); gxf_write_track_description(s, &gxf->timecode_track, s->nb_streams); return updateSize(pb, pos); }
/* send an rtp packet. sequence number is incremented, but the caller must update the timestamp itself */ void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m) { RTPMuxContext *s = s1->priv_data; av_log(s1, AV_LOG_TRACE, "rtp_send_data size=%d\n", len); /* build the RTP header */ avio_w8(s1->pb, RTP_VERSION << 6); avio_w8(s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7)); avio_wb16(s1->pb, s->seq); avio_wb32(s1->pb, s->timestamp); avio_wb32(s1->pb, s->ssrc); avio_write(s1->pb, buf1, len); avio_flush(s1->pb); s->seq = (s->seq + 1) & 0xffff; s->octet_count += len; s->packet_count++; }
/* send an rtcp sender report packet */ static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time) { RTPMuxContext *s = s1->priv_data; uint32_t rtp_ts; av_dlog(s1, "RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp); s->last_rtcp_ntp_time = ntp_time; rtp_ts = av_rescale_q(ntp_time - s->first_rtcp_ntp_time, (AVRational){1, 1000000}, s1->streams[0]->time_base) + s->base_timestamp; avio_w8(s1->pb, (RTP_VERSION << 6)); avio_w8(s1->pb, RTCP_SR); avio_wb16(s1->pb, 6); /* length in words - 1 */ avio_wb32(s1->pb, s->ssrc); avio_wb32(s1->pb, ntp_time / 1000000); avio_wb32(s1->pb, ((ntp_time % 1000000) << 32) / 1000000); avio_wb32(s1->pb, rtp_ts); avio_wb32(s1->pb, s->packet_count); avio_wb32(s1->pb, s->octet_count); avio_flush(s1->pb); }
int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par) { VPCC vpcc; int ret; ret = ff_isom_get_vpcc_features(s, par, NULL, &vpcc); if (ret < 0) return ret; avio_w8(pb, vpcc.profile); avio_w8(pb, vpcc.level); avio_w8(pb, (vpcc.bitdepth << 4) | (vpcc.chroma_subsampling << 1) | vpcc.full_range_flag); avio_w8(pb, par->color_primaries); avio_w8(pb, par->color_trc); avio_w8(pb, par->color_space); // vp9 does not have codec initialization data. avio_wb16(pb, 0); return 0; }
static int write_trailer(AVFormatContext *s) { FilmstripMuxContext *film = s->priv_data; AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; int i; avio_wb32(pb, RAND_TAG); avio_wb32(pb, film->nb_frames); avio_wb16(pb, 0); // packing method avio_wb16(pb, 0); // reserved avio_wb16(pb, st->codec->width); avio_wb16(pb, st->codec->height); avio_wb16(pb, 0); // leading avio_wb16(pb, 1/av_q2d(st->codec->time_base)); for (i = 0; i < 16; i++) avio_w8(pb, 0x00); // reserved avio_flush(pb); return 0; }
static int write_trailer(AVFormatContext *s) { FilmstripMuxContext *film = s->priv_data; AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; int i; avio_wb32(pb, RAND_TAG); avio_wb32(pb, film->nb_frames); avio_wb16(pb, 0); // packing method avio_wb16(pb, 0); // reserved avio_wb16(pb, st->codec->width); avio_wb16(pb, st->codec->height); avio_wb16(pb, 0); // leading // TODO: should be avg_frame_rate avio_wb16(pb, st->time_base.den / st->time_base.num); for (i = 0; i < 16; i++) avio_w8(pb, 0x00); // reserved return 0; }
int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count) { AVIOContext *pb; uint8_t *buf; int len; int rtcp_bytes; RTPStatistics *stats= &s->statistics; uint32_t lost; uint32_t extended_max; uint32_t expected_interval; uint32_t received_interval; uint32_t lost_interval; uint32_t expected; uint32_t fraction; uint64_t ntp_time= s->last_rtcp_ntp_time; // TODO: Get local ntp time? if (!s->rtp_ctx || (count < 1)) return -1; /* TODO: I think this is way too often; RFC 1889 has algorithm for this */ /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */ s->octet_count += count; rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) / RTCP_TX_RATIO_DEN; rtcp_bytes /= 50; // mmu_man: that's enough for me... VLC sends much less btw !? if (rtcp_bytes < 28) return -1; s->last_octet_count = s->octet_count; if (url_open_dyn_buf(&pb) < 0) return -1; // Receiver Report avio_w8(pb, (RTP_VERSION << 6) + 1); /* 1 report block */ avio_w8(pb, RTCP_RR); avio_wb16(pb, 7); /* length in words - 1 */ // our own SSRC: we use the server's SSRC + 1 to avoid conflicts avio_wb32(pb, s->ssrc + 1); avio_wb32(pb, s->ssrc); // server SSRC // some placeholders we should really fill... // RFC 1889/p64 extended_max= stats->cycles + stats->max_seq; expected= extended_max - stats->base_seq + 1; lost= expected - stats->received; lost= FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits... expected_interval= expected - stats->expected_prior; stats->expected_prior= expected; received_interval= stats->received - stats->received_prior; stats->received_prior= stats->received; lost_interval= expected_interval - received_interval; if (expected_interval==0 || lost_interval<=0) fraction= 0; else fraction = (lost_interval<<8)/expected_interval; fraction= (fraction<<24) | lost; avio_wb32(pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */ avio_wb32(pb, extended_max); /* max sequence received */ avio_wb32(pb, stats->jitter>>4); /* jitter */ if(s->last_rtcp_ntp_time==AV_NOPTS_VALUE) { avio_wb32(pb, 0); /* last SR timestamp */ avio_wb32(pb, 0); /* delay since last SR */ } else { uint32_t middle_32_bits= s->last_rtcp_ntp_time>>16; // this is valid, right? do we need to handle 64 bit values special? uint32_t delay_since_last= ntp_time - s->last_rtcp_ntp_time; avio_wb32(pb, middle_32_bits); /* last SR timestamp */ avio_wb32(pb, delay_since_last); /* delay since last SR */ } // CNAME avio_w8(pb, (RTP_VERSION << 6) + 1); /* 1 report block */ avio_w8(pb, RTCP_SDES); len = strlen(s->hostname); avio_wb16(pb, (6 + len + 3) / 4); /* length in words - 1 */ avio_wb32(pb, s->ssrc); avio_w8(pb, 0x01); avio_w8(pb, len); avio_write(pb, s->hostname, len); // padding for (len = (6 + len) % 4; len % 4; len++) { avio_w8(pb, 0); } avio_flush(pb); len = url_close_dyn_buf(pb, &buf); if ((len > 0) && buf) { int result; av_dlog(s->ic, "sending %d bytes of RR\n", len); result= url_write(s->rtp_ctx, buf, len); av_dlog(s->ic, "result from url_write: %d\n", result); av_free(buf); } return 0; }
/** * Write an RTP hint (that may contain one or more RTP packets) * for the packets in data. data contains one or more packets with a * BE32 size header. * * @param out buffer where the hints are written * @param data buffer containing RTP packets * @param size the size of the data buffer * @param trk the MOVTrack for the hint track * @param dts pointer where the timestamp for the written RTP hint is stored * @return the number of RTP packets in the written hint */ static int write_hint_packets(AVIOContext *out, const uint8_t *data, int size, MOVTrack *trk, int64_t *dts) { int64_t curpos; int64_t count_pos, entries_pos; int count = 0, entries; count_pos = avio_tell(out); /* RTPsample header */ avio_wb16(out, 0); /* packet count */ avio_wb16(out, 0); /* reserved */ while (size > 4) { uint32_t packet_len = AV_RB32(data); uint16_t seq; uint32_t ts; int32_t ts_diff; data += 4; size -= 4; if (packet_len > size || packet_len <= 12) break; if (RTP_PT_IS_RTCP(data[1])) { /* RTCP packet, just skip */ data += packet_len; size -= packet_len; continue; } if (packet_len > trk->max_packet_size) trk->max_packet_size = packet_len; seq = AV_RB16(&data[2]); ts = AV_RB32(&data[4]); if (trk->prev_rtp_ts == 0) trk->prev_rtp_ts = ts; /* Unwrap the 32-bit RTP timestamp that wraps around often * into a not (as often) wrapping 64-bit timestamp. */ ts_diff = ts - trk->prev_rtp_ts; if (ts_diff > 0) { trk->cur_rtp_ts_unwrapped += ts_diff; trk->prev_rtp_ts = ts; ts_diff = 0; } if (*dts == AV_NOPTS_VALUE) *dts = trk->cur_rtp_ts_unwrapped; count++; /* RTPpacket header */ avio_wb32(out, 0); /* relative_time */ avio_write(out, data, 2); /* RTP header */ avio_wb16(out, seq); /* RTPsequenceseed */ avio_wb16(out, ts_diff ? 4 : 0); /* reserved + flags (extra_flag) */ entries_pos = avio_tell(out); avio_wb16(out, 0); /* entry count */ if (ts_diff) { /* if extra_flag is set */ avio_wb32(out, 16); /* extra_information_length */ avio_wb32(out, 12); /* rtpoffsetTLV box */ avio_write(out, "rtpo", 4); avio_wb32(out, ts_diff); } data += 12; size -= 12; packet_len -= 12; entries = 0; /* Write one or more constructors describing the payload data */ describe_payload(data, packet_len, out, &entries, &trk->sample_queue); data += packet_len; size -= packet_len; curpos = avio_tell(out); avio_seek(out, entries_pos, SEEK_SET); avio_wb16(out, entries); avio_seek(out, curpos, SEEK_SET); } curpos = avio_tell(out); avio_seek(out, count_pos, SEEK_SET); avio_wb16(out, count); avio_seek(out, curpos, SEEK_SET); return count; }
static int rv10_write_header(AVFormatContext *ctx, int data_size, int index_pos) { RMMuxContext *rm = ctx->priv_data; AVIOContext *s = ctx->pb; StreamInfo *stream; unsigned char *data_offset_ptr, *start_ptr; const char *desc, *mimetype; int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i; int bit_rate, v, duration, flags, data_pos; AVDictionaryEntry *tag; start_ptr = s->buf_ptr; ffio_wfourcc(s, ".RMF"); avio_wb32(s,18); /* header size */ avio_wb16(s,0); avio_wb32(s,0); avio_wb32(s,4 + ctx->nb_streams); /* num headers */ ffio_wfourcc(s,"PROP"); avio_wb32(s, 50); avio_wb16(s, 0); packet_max_size = 0; packet_total_size = 0; nb_packets = 0; bit_rate = 0; duration = 0; for(i=0;i<ctx->nb_streams;i++) { StreamInfo *stream = &rm->streams[i]; bit_rate += stream->bit_rate; if (stream->packet_max_size > packet_max_size) packet_max_size = stream->packet_max_size; nb_packets += stream->nb_packets; packet_total_size += stream->packet_total_size; /* select maximum duration */ v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate); if (v > duration) duration = v; } avio_wb32(s, bit_rate); /* max bit rate */ avio_wb32(s, bit_rate); /* avg bit rate */ avio_wb32(s, packet_max_size); /* max packet size */ if (nb_packets > 0) packet_avg_size = packet_total_size / nb_packets; else packet_avg_size = 0; avio_wb32(s, packet_avg_size); /* avg packet size */ avio_wb32(s, nb_packets); /* num packets */ avio_wb32(s, duration); /* duration */ avio_wb32(s, BUFFER_DURATION); /* preroll */ avio_wb32(s, index_pos); /* index offset */ /* computation of data the data offset */ data_offset_ptr = s->buf_ptr; avio_wb32(s, 0); /* data offset : will be patched after */ avio_wb16(s, ctx->nb_streams); /* num streams */ flags = 1 | 2; /* save allowed & perfect play */ if (!s->seekable) flags |= 4; /* live broadcast */ avio_wb16(s, flags); /* comments */ ffio_wfourcc(s,"CONT"); size = 4 * 2 + 10; for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { tag = av_dict_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); if(tag) size += strlen(tag->value); } avio_wb32(s,size); avio_wb16(s,0); for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { tag = av_dict_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); put_str(s, tag ? tag->value : ""); } for(i=0;i<ctx->nb_streams;i++) { int codec_data_size; stream = &rm->streams[i]; if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) { desc = "The Audio Stream"; mimetype = "audio/x-pn-realaudio"; codec_data_size = 73; } else { desc = "The Video Stream"; mimetype = "video/x-pn-realvideo"; codec_data_size = 34; } ffio_wfourcc(s,"MDPR"); size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size; avio_wb32(s, size); avio_wb16(s, 0); avio_wb16(s, i); /* stream number */ avio_wb32(s, stream->bit_rate); /* max bit rate */ avio_wb32(s, stream->bit_rate); /* avg bit rate */ avio_wb32(s, stream->packet_max_size); /* max packet size */ if (stream->nb_packets > 0) packet_avg_size = stream->packet_total_size / stream->nb_packets; else packet_avg_size = 0; avio_wb32(s, packet_avg_size); /* avg packet size */ avio_wb32(s, 0); /* start time */ avio_wb32(s, BUFFER_DURATION); /* preroll */ /* duration */ if (!s->seekable || !stream->total_frames) avio_wb32(s, (int)(3600 * 1000)); else avio_wb32(s, (int)(stream->total_frames * 1000 / stream->frame_rate)); put_str8(s, desc); put_str8(s, mimetype); avio_wb32(s, codec_data_size); if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) { int coded_frame_size, fscode, sample_rate; sample_rate = stream->enc->sample_rate; coded_frame_size = (stream->enc->bit_rate * stream->enc->frame_size) / (8 * sample_rate); /* audio codec info */ avio_write(s, ".ra", 3); avio_w8(s, 0xfd); avio_wb32(s, 0x00040000); /* version */ ffio_wfourcc(s, ".ra4"); avio_wb32(s, 0x01b53530); /* stream length */ avio_wb16(s, 4); /* unknown */ avio_wb32(s, 0x39); /* header size */ switch(sample_rate) { case 48000: case 24000: case 12000: fscode = 1; break; default: case 44100: case 22050: case 11025: fscode = 2; break; case 32000: case 16000: case 8000: fscode = 3; } avio_wb16(s, fscode); /* codec additional info, for AC-3, seems to be a frequency code */ /* special hack to compensate rounding errors... */ if (coded_frame_size == 557) coded_frame_size--; avio_wb32(s, coded_frame_size); /* frame length */ avio_wb32(s, 0x51540); /* unknown */ avio_wb32(s, stream->enc->bit_rate / 8 * 60); /* bytes per minute */ avio_wb32(s, stream->enc->bit_rate / 8 * 60); /* bytes per minute */ avio_wb16(s, 0x01); /* frame length : seems to be very important */ avio_wb16(s, coded_frame_size); avio_wb32(s, 0); /* unknown */ avio_wb16(s, stream->enc->sample_rate); /* sample rate */ avio_wb32(s, 0x10); /* unknown */ avio_wb16(s, stream->enc->channels); put_str8(s, "Int0"); /* codec name */ if (stream->enc->codec_tag) { avio_w8(s, 4); /* tag length */ avio_wl32(s, stream->enc->codec_tag); } else { av_log(ctx, AV_LOG_ERROR, "Invalid codec tag\n"); return -1; } avio_wb16(s, 0); /* title length */ avio_wb16(s, 0); /* author length */ avio_wb16(s, 0); /* copyright length */ avio_w8(s, 0); /* end of header */ } else { /* video codec info */ avio_wb32(s,34); /* size */ ffio_wfourcc(s, "VIDO"); if(stream->enc->codec_id == AV_CODEC_ID_RV10) ffio_wfourcc(s,"RV10"); else ffio_wfourcc(s,"RV20"); avio_wb16(s, stream->enc->width); avio_wb16(s, stream->enc->height); avio_wb16(s, (int) stream->frame_rate); /* frames per seconds ? */ avio_wb32(s,0); /* unknown meaning */ avio_wb16(s, (int) stream->frame_rate); /* unknown meaning */ avio_wb32(s,0); /* unknown meaning */ avio_wb16(s, 8); /* unknown meaning */ /* Seems to be the codec version: only use basic H263. The next versions seems to add a diffential DC coding as in MPEG... nothing new under the sun */ if(stream->enc->codec_id == AV_CODEC_ID_RV10) avio_wb32(s,0x10000000); else avio_wb32(s,0x20103001); //avio_wb32(s,0x10003000); } } /* patch data offset field */ data_pos = s->buf_ptr - start_ptr; rm->data_pos = data_pos; data_offset_ptr[0] = data_pos >> 24; data_offset_ptr[1] = data_pos >> 16; data_offset_ptr[2] = data_pos >> 8; data_offset_ptr[3] = data_pos; /* data stream */ ffio_wfourcc(s, "DATA"); avio_wb32(s,data_size + 10 + 8); avio_wb16(s,0); avio_wb32(s, nb_packets); /* number of packets */ avio_wb32(s,0); /* next data header */ return 0; }
const int isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) { // extradata from bytestream h264, convert to avcC atom data for bitstream if (len > 6) { /* check for h264 start code */ if (VDA_RB32(data) == 0x00000001 || VDA_RB24(data) == 0x000001) { uint8_t *buf=NULL, *end, *start; uint32_t sps_size=0, pps_size=0; uint8_t *sps=0, *pps=0; int ret = avc_parse_nal_units_buf(data, &buf, &len); if (ret < 0) return ret; start = buf; end = buf + len; /* look for sps and pps */ while (buf < end) { unsigned int size; uint8_t nal_type; size = VDA_RB32(buf); nal_type = buf[4] & 0x1f; if (nal_type == 7) /* SPS */ { sps = buf + 4; sps_size = size; //parse_sps(sps+1, sps_size-1); } else if (nal_type == 8) /* PPS */ { pps = buf + 4; pps_size = size; } buf += size + 4; } if (!sps) { LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid data (sps)"); return -1; } avio_w8(pb, 1); /* version */ avio_w8(pb, sps[1]); /* profile */ avio_w8(pb, sps[2]); /* profile compat */ avio_w8(pb, sps[3]); /* level */ avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ avio_wb16(pb, sps_size); avio_write(pb, sps, sps_size); if (pps) { avio_w8(pb, 1); /* number of pps */ avio_wb16(pb, pps_size); avio_write(pb, pps, pps_size); } av_free(start); } else { avio_write(pb, data, len); } } return 0; }
static int aiff_write_header(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; AVExtFloat sample_rate; int aifc = 0; /* First verify if format is ok */ if (!enc->codec_tag) return -1; if (enc->codec_tag != MKTAG('N','O','N','E')) aifc = 1; /* FORM AIFF header */ ffio_wfourcc(pb, "FORM"); aiff->form = avio_tell(pb); avio_wb32(pb, 0); /* file length */ ffio_wfourcc(pb, aifc ? "AIFC" : "AIFF"); if (aifc) { // compressed audio enc->bits_per_coded_sample = 16; if (!enc->block_align) { av_log(s, AV_LOG_ERROR, "block align not set\n"); return -1; } /* Version chunk */ ffio_wfourcc(pb, "FVER"); avio_wb32(pb, 4); avio_wb32(pb, 0xA2805140); } if (enc->channels > 2 && enc->channel_layout) { ffio_wfourcc(pb, "CHAN"); avio_wb32(pb, 12); ff_mov_write_chan(pb, enc->channel_layout); } /* Common chunk */ ffio_wfourcc(pb, "COMM"); avio_wb32(pb, aifc ? 24 : 18); /* size */ avio_wb16(pb, enc->channels); /* Number of channels */ aiff->frames = avio_tell(pb); avio_wb32(pb, 0); /* Number of frames */ if (!enc->bits_per_coded_sample) enc->bits_per_coded_sample = av_get_bits_per_sample(enc->codec_id); if (!enc->bits_per_coded_sample) { av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n"); return -1; } if (!enc->block_align) enc->block_align = (enc->bits_per_coded_sample * enc->channels) >> 3; avio_wb16(pb, enc->bits_per_coded_sample); /* Sample size */ sample_rate = av_dbl2ext((double)enc->sample_rate); avio_write(pb, (uint8_t*)&sample_rate, sizeof(sample_rate)); if (aifc) { avio_wl32(pb, enc->codec_tag); avio_wb16(pb, 0); } /* Sound data chunk */ ffio_wfourcc(pb, "SSND"); aiff->ssnd = avio_tell(pb); /* Sound chunk size */ avio_wb32(pb, 0); /* Sound samples data size */ avio_wb32(pb, 0); /* Data offset */ avio_wb32(pb, 0); /* Block-size (block align) */ avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); /* Data is starting here */ avio_flush(pb); return 0; }
/* * Write an empty XING header and initialize respective data. */ static void mp3_write_xing(AVFormatContext *s) { MP3Context *mp3 = s->priv_data; AVCodecContext *codec = s->streams[mp3->audio_stream_idx]->codec; AVDictionaryEntry *enc = av_dict_get(s->streams[mp3->audio_stream_idx]->metadata, "encoder", NULL, 0); AVIOContext *dyn_ctx; int32_t header; MPADecodeHeader mpah; int srate_idx, i, channels; int bitrate_idx; int best_bitrate_idx; int best_bitrate_error = INT_MAX; int ret; int ver = 0; int lsf, bytes_needed; if (!s->pb->seekable || !mp3->write_xing) return; for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) { const uint16_t base_freq = avpriv_mpa_freq_tab[i]; if (codec->sample_rate == base_freq) ver = 0x3; // MPEG 1 else if (codec->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2 else if (codec->sample_rate == base_freq / 4) ver = 0x0; // MPEG 2.5 else continue; srate_idx = i; break; } if (i == FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) { av_log(s, AV_LOG_WARNING, "Unsupported sample rate, not writing Xing " "header.\n"); return; } switch (codec->channels) { case 1: channels = MPA_MONO; break; case 2: channels = MPA_STEREO; break; default: av_log(s, AV_LOG_WARNING, "Unsupported number of channels, " "not writing Xing header.\n"); return; } /* dummy MPEG audio header */ header = 0xff << 24; // sync header |= (0x7 << 5 | ver << 3 | 0x1 << 1 | 0x1) << 16; // sync/audio-version/layer 3/no crc*/ header |= (srate_idx << 2) << 8; header |= channels << 6; lsf = !((header & (1 << 20) && header & (1 << 19))); mp3->xing_offset = xing_offtbl[ver != 3][channels == 1] + 4; bytes_needed = mp3->xing_offset + XING_SIZE; for (bitrate_idx = 1; bitrate_idx < 15; bitrate_idx++) { int bit_rate = 1000 * avpriv_mpa_bitrate_tab[lsf][3 - 1][bitrate_idx]; int error = FFABS(bit_rate - codec->bit_rate); if (error < best_bitrate_error){ best_bitrate_error = error; best_bitrate_idx = bitrate_idx; } } for (bitrate_idx = best_bitrate_idx; bitrate_idx < 15; bitrate_idx++) { int32_t mask = bitrate_idx << (4 + 8); header |= mask; avpriv_mpegaudio_decode_header(&mpah, header); if (bytes_needed <= mpah.frame_size) break; header &= ~mask; } ret = avio_open_dyn_buf(&dyn_ctx); if (ret < 0) return; avio_wb32(dyn_ctx, header); avpriv_mpegaudio_decode_header(&mpah, header); av_assert0(mpah.frame_size >= bytes_needed); ffio_fill(dyn_ctx, 0, mp3->xing_offset - 4); ffio_wfourcc(dyn_ctx, "Xing"); avio_wb32(dyn_ctx, 0x01 | 0x02 | 0x04 | 0x08); // frames / size / TOC / vbr scale mp3->size = mpah.frame_size; mp3->want = 1; avio_wb32(dyn_ctx, 0); // frames avio_wb32(dyn_ctx, 0); // size // TOC for (i = 0; i < XING_TOC_SIZE; i++) avio_w8(dyn_ctx, 255 * i / XING_TOC_SIZE); // vbr quality // we write it, because some (broken) tools always expect it to be present avio_wb32(dyn_ctx, 0); // encoder short version string if (enc) { uint8_t encoder_str[9] = { 0 }; memcpy(encoder_str, enc->value, FFMIN(strlen(enc->value), sizeof(encoder_str))); avio_write(dyn_ctx, encoder_str, sizeof(encoder_str)); } else ffio_fill(dyn_ctx, 0, 9); avio_w8(dyn_ctx, 0); // tag revision 0 / unknown vbr method avio_w8(dyn_ctx, 0); // unknown lowpass filter value ffio_fill(dyn_ctx, 0, 8); // empty replaygain fields avio_w8(dyn_ctx, 0); // unknown encoding flags avio_w8(dyn_ctx, 0); // unknown abr/minimal bitrate // encoder delay if (codec->initial_padding >= 1 << 12) { av_log(s, AV_LOG_WARNING, "Too many samples of initial padding.\n"); avio_wb24(dyn_ctx, 0); } else { avio_wb24(dyn_ctx, codec->initial_padding << 12); } avio_w8(dyn_ctx, 0); // misc avio_w8(dyn_ctx, 0); // mp3gain avio_wb16(dyn_ctx, 0); // preset // audio length and CRCs (will be updated later) avio_wb32(dyn_ctx, 0); // music length avio_wb16(dyn_ctx, 0); // music crc avio_wb16(dyn_ctx, 0); // tag crc ffio_fill(dyn_ctx, 0, mpah.frame_size - bytes_needed); mp3->xing_frame_size = avio_close_dyn_buf(dyn_ctx, &mp3->xing_frame); mp3->xing_frame_offset = avio_tell(s->pb); avio_write(s->pb, mp3->xing_frame, mp3->xing_frame_size); mp3->audio_size = mp3->xing_frame_size; }
static void put_amf_string(AVIOContext *pb, const char *str) { size_t len = strlen(str); avio_wb16(pb, len); avio_write(pb, str, len); }
static int gxf_write_umf_media_description(AVFormatContext *s) { GXFContext *gxf = s->priv_data; AVIOContext *pb = s->pb; int64_t pos; int i, j; pos = avio_tell(pb); gxf->umf_media_offset = pos - gxf->umf_start_offset; for (i = 0; i <= s->nb_streams; ++i) { GXFStreamContext *sc; int64_t startpos, curpos; if (i == s->nb_streams) sc = &gxf->timecode_track; else sc = s->streams[i]->priv_data; startpos = avio_tell(pb); avio_wl16(pb, 0); /* length */ avio_wl16(pb, sc->media_info); avio_wl16(pb, 0); /* reserved */ avio_wl16(pb, 0); /* reserved */ avio_wl32(pb, gxf->nb_fields); avio_wl32(pb, 0); /* attributes rw, ro */ avio_wl32(pb, 0); /* mark in */ avio_wl32(pb, gxf->nb_fields); /* mark out */ avio_write(pb, ES_NAME_PATTERN, strlen(ES_NAME_PATTERN)); avio_wb16(pb, sc->media_info); for (j = strlen(ES_NAME_PATTERN)+2; j < 88; j++) avio_w8(pb, 0); avio_wl32(pb, sc->track_type); avio_wl32(pb, sc->sample_rate); avio_wl32(pb, sc->sample_size); avio_wl32(pb, 0); /* reserved */ if (sc == &gxf->timecode_track) gxf_write_umf_media_timecode(pb, gxf->tc.drop); else { AVStream *st = s->streams[i]; switch (st->codec->codec_id) { case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: gxf_write_umf_media_mpeg(pb, st); break; case CODEC_ID_PCM_S16LE: gxf_write_umf_media_audio(pb, sc); break; case CODEC_ID_DVVIDEO: gxf_write_umf_media_dv(pb, sc); break; } } curpos = avio_tell(pb); avio_seek(pb, startpos, SEEK_SET); avio_wl16(pb, curpos - startpos); avio_seek(pb, curpos, SEEK_SET); } return avio_tell(pb) - pos; }