示例#1
0
文件: ffmenc.c 项目: 309746069/FFmpeg
static int ffm_write_recommended_config(AVIOContext *pb, AVCodecContext *ctx, unsigned tag,
                                        const char *configuration)
{
    int ret;
    const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id);
    AVIOContext *tmp;
    AVDictionaryEntry *t = NULL;
    AVDictionary *all = NULL, *comm = NULL, *prv = NULL;
    char *buf = NULL;

    if (!enc || !enc->priv_class || !enc->priv_data_size) {
        /* codec is not known/has no private options, so save everything as common options */
        if (avio_open_dyn_buf(&tmp) < 0)
            return AVERROR(ENOMEM);
        avio_put_str(tmp, configuration);
        write_header_chunk(pb, tmp, tag);
        return 0;
    }

    if ((ret = av_dict_parse_string(&all, configuration, "=", ",", 0)) < 0)
        return ret;

    while ((t = av_dict_get(all, "", t, AV_DICT_IGNORE_SUFFIX))) {
        if (av_opt_find((void *)&enc->priv_class, t->key, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)) {
            if ((ret = av_dict_set(&prv, t->key, t->value, 0)) < 0)
                goto fail;
        } else if ((ret = av_dict_set(&comm, t->key, t->value, 0)) < 0)
            goto fail;
    }

    if (comm) {
        if ((ret = av_dict_get_string(comm, &buf, '=', ',')) < 0 ||
            (ret = avio_open_dyn_buf(&tmp)) < 0)
            goto fail;
        avio_put_str(tmp, buf);
        av_freep(&buf);
        write_header_chunk(pb, tmp, tag);
    }
    if (prv) {
        if ((ret = av_dict_get_string(prv, &buf, '=', ',')) < 0 ||
            (ret = avio_open_dyn_buf(&tmp)) < 0)
            goto fail;
        avio_put_str(tmp, buf);
        write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V'));
    }

  fail:
    av_free(buf);
    av_dict_free(&all);
    av_dict_free(&comm);
    av_dict_free(&prv);
    return ret;
}
void FFMPEG_Wrapper::get_trailer(std::vector<uint8_t>& trailer)
{
  std::size_t size;
  uint8_t* output_buf;

  boost::mutex::scoped_lock lock(frame_mutex_);

  if (avio_open_dyn_buf(&ffmpeg_format_context_->pb) >= 0)
  {
    ffmpeg_format_context_->pb->seekable = 0;

    if (av_write_trailer(ffmpeg_format_context_) < 0)
    {
      fprintf(stderr, "Error occurred when opening output file\n");
      return;
    }

    size = avio_close_dyn_buf(ffmpeg_format_context_->pb, &output_buf);

    // copy header buffer to vector
    trailer.resize(size);
    memcpy(&trailer[0], output_buf, size);

    av_free(output_buf);
  }
}
示例#3
0
// Destructor  //call flush before any encoder gets deleted
EncoderFfmpegCore::~EncoderFfmpegCore() {

    qDebug() << "EncoderFfmpegCore::~EncoderFfmpegCore()";
    av_freep(&m_pSamples);
    av_freep(&m_pFltSamples);

    avio_open_dyn_buf(&m_pEncodeFormatCtx->pb);
    if (av_write_trailer(m_pEncodeFormatCtx) != 0) {
        qDebug() << "Multiplexer: failed to write a trailer.";
    } else {
        unsigned char *l_strBuffer = NULL;
        int l_iBufferLen = 0;
        l_iBufferLen = avio_close_dyn_buf(m_pEncodeFormatCtx->pb,
                                          (uint8_t**)(&l_strBuffer));
        m_pCallback->write(NULL, l_strBuffer, 0, l_iBufferLen);
        av_free(l_strBuffer);
    }


    if (m_pStream != NULL) {
        avcodec_close(m_pStream->codec);
    }

    if (m_pEncodeFormatCtx != NULL) {
        av_free(m_pEncodeFormatCtx);
    }

    // Close buffer
    delete m_pResample;
}
示例#4
0
static int sff_write_header(AVFormatContext *ctx)
{
	uint32_t size = 0; 
	uint8_t *buf = NULL;
	int ret = 0;
	AVIOContext *pb = NULL, *old = ctx->pb;
	if(!ctx ){
		return -1;
	}	

	if(avio_open_dyn_buf(&pb) < 0){
		return -1;
	}
	ctx->pb = pb;
	if(avformat_write_header(ctx, NULL) < 0){
		ctx->pb = old;
		return -1;
	}
		
	size = avio_close_dyn_buf(ctx->pb, &buf);
	ctx->pb = old;
	if(size > 0)
		ret = sff_write_block(ctx->pb, 1, buf, size);
	av_freep(&buf);	
	return ret;
}
示例#5
0
static char *choose_pix_fmts(OutputStream *ost)
{
    AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0);
    if (strict_dict)
        // used by choose_pixel_fmt() and below
        av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0);

     if (ost->keep_pix_fmt) {
        if (ost->filter)
            avfilter_graph_set_auto_convert(ost->filter->graph->graph,
                                            AVFILTER_AUTO_CONVERT_NONE);
        if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE)
            return NULL;
        return av_strdup(av_get_pix_fmt_name(ost->enc_ctx->pix_fmt));
    }
    if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
        return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt)));
    } else if (ost->enc && ost->enc->pix_fmts) {
        const enum AVPixelFormat *p;
        AVIOContext *s = NULL;
        uint8_t *ret;
        int len;

        if (avio_open_dyn_buf(&s) < 0)
            exit_program(1);

        p = ost->enc->pix_fmts;
        if (ost->enc_ctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
            if (ost->enc_ctx->codec_id == AV_CODEC_ID_MJPEG) {
                p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE };
            } else if (ost->enc_ctx->codec_id == AV_CODEC_ID_LJPEG) {
                p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P,
                                                    AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE };
            }
示例#6
0
文件: ffmenc.c 项目: 309746069/FFmpeg
static int ffm_write_header_codec_private_ctx(AVFormatContext *s, AVCodecContext *ctx, int type)
{
    AVIOContext *pb = s->pb;
    AVIOContext *tmp;
    char *buf = NULL;
    int ret;
    const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id);

    if (!enc) {
        av_log(s, AV_LOG_WARNING, "Stream codec is not found. Codec private options are not stored.\n");
        return 0;
    }
    if (ctx->priv_data && enc->priv_class && enc->priv_data_size) {
        if ((ret = av_opt_serialize(ctx->priv_data, AV_OPT_FLAG_ENCODING_PARAM | type,
                                    AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ',')) < 0)
            return ret;
        if (buf && strlen(buf)) {
            if (avio_open_dyn_buf(&tmp) < 0) {
                av_free(buf);
                return AVERROR(ENOMEM);
            }
            avio_put_str(tmp, buf);
            write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V'));
        }
        av_free(buf);
    }
    return 0;
}
void FFMPEG_Wrapper::get_header(std::vector<uint8_t>& header)
{
  boost::mutex::scoped_lock lock(frame_mutex_);

  std::size_t size;
  uint8_t* output_buf;

  // define meta data
  av_dict_set(&ffmpeg_format_context_->metadata, "author"   , "ROS topic http streamer"   , 0);
  av_dict_set(&ffmpeg_format_context_->metadata, "comment"  , "this is awesome"  , 0);
  av_dict_set(&ffmpeg_format_context_->metadata, "copyright", "BSD", 0);
  av_dict_set(&ffmpeg_format_context_->metadata, "title"    , "ROS Topic Stream" , 0);

  if (avio_open_dyn_buf(&ffmpeg_format_context_->pb) >= 0)
  {
    ffmpeg_format_context_->pb->seekable = 0;

    if (avformat_write_header(ffmpeg_format_context_, NULL) < 0)
    {
      fprintf(stderr, "Error occurred when opening output file\n");
      return;
    }

    //av_dict_free(&ffmpeg_format_context_->metadata);

    size = avio_close_dyn_buf(ffmpeg_format_context_->pb, &output_buf);

    // copy header buffer to vector
    header.resize(size);
    memcpy(&header[0], output_buf, size);

    av_free(output_buf);
  }
}
static int latm_parse_packet(AVFormatContext *ctx, PayloadContext *data,
                             AVStream *st, AVPacket *pkt, uint32_t *timestamp,
                             const uint8_t *buf, int len, int flags)
{
	int ret, cur_len;

	if (buf)
	{
		if (!data->dyn_buf || data->timestamp != *timestamp)
		{
			av_freep(&data->buf);
			if (data->dyn_buf)
				avio_close_dyn_buf(data->dyn_buf, &data->buf);
			data->dyn_buf = NULL;
			av_freep(&data->buf);

			data->timestamp = *timestamp;
			if ((ret = avio_open_dyn_buf(&data->dyn_buf)) < 0)
				return ret;
		}
		avio_write(data->dyn_buf, buf, len);

		if (!(flags & RTP_FLAG_MARKER))
			return AVERROR(EAGAIN);
		av_free(data->buf);
		data->len = avio_close_dyn_buf(data->dyn_buf, &data->buf);
		data->dyn_buf = NULL;
		data->pos = 0;
	}

	if (!data->buf)
	{
		av_log(ctx, AV_LOG_ERROR, "No data available yet\n");
		return AVERROR(EIO);
	}

	cur_len = 0;
	while (data->pos < data->len)
	{
		uint8_t val = data->buf[data->pos++];
		cur_len += val;
		if (val != 0xff)
			break;
	}
	if (data->pos + cur_len > data->len)
	{
		av_log(ctx, AV_LOG_ERROR, "Malformed LATM packet\n");
		return AVERROR(EIO);
	}

	if ((ret = av_new_packet(pkt, cur_len)) < 0)
		return ret;
	memcpy(pkt->data, data->buf + data->pos, cur_len);
	data->pos += cur_len;
	pkt->stream_index = st->index;
	return data->pos < data->len;
}
示例#9
0
文件: movenchint.c 项目: AVLeo/libav
int ff_mov_add_hinted_packet(AVFormatContext *s, AVPacket *pkt,
                             int track_index, int sample,
                             uint8_t *sample_data, int sample_size)
{
    MOVMuxContext *mov = s->priv_data;
    MOVTrack *trk = &mov->tracks[track_index];
    AVFormatContext *rtp_ctx = trk->rtp_ctx;
    uint8_t *buf = NULL;
    int size;
    AVIOContext *hintbuf = NULL;
    AVPacket hint_pkt;
    int ret = 0, count;

    if (!rtp_ctx)
        return AVERROR(ENOENT);
    if (!rtp_ctx->pb)
        return AVERROR(ENOMEM);

    if (sample_data)
        sample_queue_push(&trk->sample_queue, sample_data, sample_size, sample);
    else
        sample_queue_push(&trk->sample_queue, pkt->data, pkt->size, sample);

    /* Feed the packet to the RTP muxer */
    ff_write_chained(rtp_ctx, 0, pkt, s);

    /* Fetch the output from the RTP muxer, open a new output buffer
     * for next time. */
    size = avio_close_dyn_buf(rtp_ctx->pb, &buf);
    if ((ret = ffio_open_dyn_packet_buf(&rtp_ctx->pb,
                                        RTP_MAX_PACKET_SIZE)) < 0)
        goto done;

    if (size <= 0)
        goto done;

    /* Open a buffer for writing the hint */
    if ((ret = avio_open_dyn_buf(&hintbuf)) < 0)
        goto done;
    av_init_packet(&hint_pkt);
    count = write_hint_packets(hintbuf, buf, size, trk, &hint_pkt.dts);
    av_freep(&buf);

    /* Write the hint data into the hint track */
    hint_pkt.size = size = avio_close_dyn_buf(hintbuf, &buf);
    hint_pkt.data = buf;
    hint_pkt.pts  = hint_pkt.dts;
    hint_pkt.stream_index = track_index;
    if (pkt->flags & AV_PKT_FLAG_KEY)
        hint_pkt.flags |= AV_PKT_FLAG_KEY;
    if (count > 0)
        ff_mov_write_packet(s, &hint_pkt);
done:
    av_free(buf);
    sample_queue_retain(&trk->sample_queue);
    return ret;
}
示例#10
0
static char *choose_pix_fmts(OutputStream *ost)
{
    AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0);
    if(strict_dict)
        // used by choose_pixel_fmt() and below
    {
        av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0);
    }
    
    if(ost->keep_pix_fmt)
    {
        if(ost->filter)
            avfilter_graph_set_auto_convert(ost->filter->graph->graph,
                                            AVFILTER_AUTO_CONVERT_NONE);
        if(ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE)
        {
            return NULL;
        }
        return av_strdup(av_get_pix_fmt_name(ost->enc_ctx->pix_fmt));
    }
    if(ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE)
    {
        return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt)));
    }
    else if(ost->enc && ost->enc->pix_fmts)
    {
        const enum AVPixelFormat *p;
        AVIOContext *s = NULL;
        uint8_t *ret;
        int len;
        
        if(avio_open_dyn_buf(&s) < 0)
        {
            exit_program(1);
        }
        
        p = ost->enc->pix_fmts;
        if(ost->enc_ctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)
        {
            p = get_compliance_unofficial_pix_fmts(ost->enc_ctx->codec_id, p);
        }
        
        for(; *p != AV_PIX_FMT_NONE; p++)
        {
            const char *name = av_get_pix_fmt_name(*p);
            avio_printf(s, "%s|", name);
        }
        len = avio_close_dyn_buf(s, &ret);
        ret[len - 1] = 0;
        return ret;
    }
    else
    {
        return NULL;
    }
}
示例#11
0
static int chunk_start(AVFormatContext *s)
{
    WebMChunkContext *wc = s->priv_data;
    AVFormatContext *oc = wc->avf;
    int ret;

    ret = avio_open_dyn_buf(&oc->pb);
    if (ret < 0)
        return ret;
    wc->chunk_index++;
    return 0;
}
示例#12
0
文件: avc.c 项目: AVbin/libav
int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
{
    AVIOContext *pb;
    int ret = avio_open_dyn_buf(&pb);
    if(ret < 0)
        return ret;

    ff_avc_parse_nal_units(pb, buf_in, *size);

    av_freep(buf);
    *size = avio_close_dyn_buf(pb, buf);
    return 0;
}
示例#13
0
文件: id3v2.c 项目: genesi/libav
/**
 * Decode characters to UTF-8 according to encoding type. The decoded buffer is
 * always null terminated. Stop reading when either *maxread bytes are read from
 * pb or U+0000 character is found.
 *
 * @param dst Pointer where the address of the buffer with the decoded bytes is
 * stored. Buffer must be freed by caller.
 * @param maxread Pointer to maximum number of characters to read from the
 * AVIOContext. After execution the value is decremented by the number of bytes
 * actually read.
 * @returns 0 if no error occurred, dst is uninitialized on error
 */
static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding,
                      uint8_t **dst, int *maxread)
{
    int ret;
    uint8_t tmp;
    uint32_t ch = 1;
    int left = *maxread;
    unsigned int (*get)(AVIOContext*) = avio_rb16;
    AVIOContext *dynbuf;

    if ((ret = avio_open_dyn_buf(&dynbuf)) < 0) {
        av_log(s, AV_LOG_ERROR, "Error opening memory stream\n");
        return ret;
    }

    switch (encoding) {

    case ID3v2_ENCODING_ISO8859:
        while (left && ch) {
            ch = avio_r8(pb);
            PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
            left--;
        }
        break;

    case ID3v2_ENCODING_UTF16BOM:
        if ((left -= 2) < 0) {
            av_log(s, AV_LOG_ERROR, "Cannot read BOM value, input too short\n");
            avio_close_dyn_buf(dynbuf, dst);
            av_freep(dst);
            return AVERROR_INVALIDDATA;
        }
        switch (avio_rb16(pb)) {
        case 0xfffe:
            get = avio_rl16;
        case 0xfeff:
            break;
        default:
            av_log(s, AV_LOG_ERROR, "Incorrect BOM value\n");
            avio_close_dyn_buf(dynbuf, dst);
            av_freep(dst);
            *maxread = left;
            return AVERROR_INVALIDDATA;
        }
        // fall-through

    case ID3v2_ENCODING_UTF16BE:
        while ((left > 1) && ch) {
            GET_UTF16(ch, ((left -= 2) >= 0 ? get(pb) : 0), break;)
            PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
        }
示例#14
0
static void put_str16(AVIOContext *s, const char *tag)
{
    int len;
    uint8_t *pb;
    AVIOContext *dyn_buf;
    if (avio_open_dyn_buf(&dyn_buf) < 0)
        return;

    avio_put_str16le(dyn_buf, tag);
    len = avio_close_dyn_buf(dyn_buf, &pb);
    avio_wl16(s, len);
    avio_write(s, pb, len);
    av_freep(&pb);
}
示例#15
0
void ff_rtp_send_punch_packets(URLContext *rtp_handle)
{
    AVIOContext *pb;
    uint8_t *buf;
    int len;

    /* Send a small RTP packet */
    if (avio_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 = avio_close_dyn_buf(pb, &buf);
    if ((len > 0) && buf)
        ffurl_write(rtp_handle, buf, len);
    av_free(buf);

    /* Send a minimal RTCP RR */
    if (avio_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 = avio_close_dyn_buf(pb, &buf);
    if ((len > 0) && buf)
        ffurl_write(rtp_handle, buf, len);
    av_free(buf);
}
示例#16
0
bool MediaConverter::imgs2media(LPRImage *pRawImages[], size_t imgCount, EventMedia &eventMedia)
{
	if (imgCount == 0)
	{
		printf("Input is empty.\n");
		return true;
	}
	//////////////////////////////////////////////////////////////////////////
	if(!initialize(pRawImages[0], "temp.avi"))
	{
		printf("Failed to initialize.\n");
		return false;
	}
	//////////////////////////////////////////////////////////////////////////
	if (!(mOutputFormatCtxPtr->flags & AVFMT_NOFILE))
	{
		/*if (avio_open(&mOutputFormatCtxPtr->pb, mediaName.c_str(), AVIO_FLAG_WRITE) < 0)
		{
		printf("Could not open %s.\n", mediaName.c_str());
		return false;
		}*/
		if (avio_open_dyn_buf(&mOutputFormatCtxPtr->pb) < 0)
		{
			printf("Could not open avio buff.\n");
			return false;
		}
	}
	//////////////////////////////////////////////////////////////////////////
	// Output
	avformat_write_header(mOutputFormatCtxPtr, NULL);
	for (size_t i = 0; i < imgCount; ++ i)
		outputFrame(pRawImages[i]);
	flushFrames();
	av_write_trailer(mOutputFormatCtxPtr);
	//////////////////////////////////////////////////////////////////////////
	if (!(mOutputFormatCtxPtr->flags & AVFMT_NOFILE))
	{
		//avio_close(mOutputFormatCtxPtr->pb);
		eventMedia.mBufferSize = avio_close_dyn_buf(mOutputFormatCtxPtr->pb, &eventMedia.mBufferPtr);
	}
	//////////////////////////////////////////////////////////////////////////
	// 清理环境
	uninitialize();

	return true;
}
示例#17
0
static int asf_write_markers(AVFormatContext *s)
{
    ASFContext *asf = s->priv_data;
    AVIOContext *pb = s->pb;
    int i;
    AVRational scale = {1, 10000000};
    int64_t hpos = put_header(pb, &ff_asf_marker_header);

    ff_put_guid(pb, &ff_asf_reserved_4);// ASF spec mandates this reserved value
    avio_wl32(pb, s->nb_chapters);     // markers count
    avio_wl16(pb, 0);                  // ASF spec mandates 0 for this
    avio_wl16(pb, 0);                  // name length 0, no name given

    for (i = 0; i < s->nb_chapters; i++) {
        AVChapter *c = s->chapters[i];
        AVDictionaryEntry *t = av_dict_get(c->metadata, "title", NULL, 0);
        int64_t pres_time = av_rescale_q(c->start, c->time_base, scale);
        uint64_t offset;
        int32_t send_time = get_send_time(asf, pres_time, &offset);
        int len = 0;
        uint8_t *buf;
        AVIOContext *dyn_buf;
        if (t) {
            if (avio_open_dyn_buf(&dyn_buf) < 0)
                return AVERROR(ENOMEM);
            avio_put_str16le(dyn_buf, t->value);
            len = avio_close_dyn_buf(dyn_buf, &buf);
        }
        avio_wl64(pb, offset);            // offset of the packet with send_time
        avio_wl64(pb, pres_time + PREROLL_TIME * 10000); // presentation time
        avio_wl16(pb, 12 + len);          // entry length
        avio_wl32(pb, send_time);         // send time
        avio_wl32(pb, 0);                 // flags, should be 0
        avio_wl32(pb, len / 2);           // marker desc length in WCHARS!
        if (t) {
            avio_write(pb, buf, len);     // marker desc
            av_freep(&buf);
        }
    }
    end_header(pb, hpos);
    return 0;
}
示例#18
0
static int sff_write_packet(AVFormatContext *ctx, AVPacket *pkt)
{
	AVIOContext *pb = NULL, *old = NULL;
	uint8_t *buf = NULL;
	int size = 0, frame_size = -1, ret = -1;
	static int seq = 0;
	++seq;

	if(!ctx || !ctx->pb)return 0;
	if(avio_open_dyn_buf(&pb) < 0){
		return -1;
	}
	pb->seekable = 0;
	old = ctx->pb;
	ctx->pb = pb;
	
	/*add more pkt info if needed, here stream_index only for illustration.*/
	if(pkt){
		avio_wb32(pb, pkt->stream_index);
		ret = av_interleaved_write_frame(ctx, pkt);
	}else{
		avio_wb32(pb, (uint32_t)-1);
		ret = av_write_trailer(ctx);
	}
	size = avio_close_dyn_buf(pb, &buf);
	frame_size = size - 4;
	ctx->pb = old;

	if(frame_size <= 0){
		//printf("write frame fail err %x %d:%d\n", ret, seq, frame_size);
		goto fail;/*its ok*/
	}
	if(ret < 0){
		printf("write frame fail err %x %d:%d\n", ret, seq, frame_size);
		goto fail;
	}
	ret = sff_write_block(ctx->pb, 2, buf, size);
fail:
	av_freep(&buf);	
	return ret;
}
示例#19
0
文件: ffmenc.c 项目: 309746069/FFmpeg
static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecContext *ctx, unsigned tag, int type)
{
    AVIOContext *tmp;
    char *buf = NULL;
    int ret, need_coma = 0;

#define SKIP_DEFAULTS   AV_OPT_SERIALIZE_SKIP_DEFAULTS
#define OPT_FLAGS_EXACT AV_OPT_SERIALIZE_OPT_FLAGS_EXACT
#define ENC             AV_OPT_FLAG_ENCODING_PARAM

    if (avio_open_dyn_buf(&tmp) < 0)
        return AVERROR(ENOMEM);
    if ((ret = av_opt_serialize(ctx, ENC | type, SKIP_DEFAULTS, &buf, '=', ',')) < 0)
        goto fail;
    if (buf && strlen(buf)) {
        avio_write(tmp, buf, strlen(buf));
        av_freep(&buf);
        need_coma = 1;
    }
    if ((ret = av_opt_serialize(ctx, 0, SKIP_DEFAULTS | OPT_FLAGS_EXACT, &buf, '=', ',')) < 0)
        goto fail;
    if (buf && strlen(buf)) {
        if (need_coma)
            avio_w8(tmp, ',');
        avio_write(tmp, buf, strlen(buf));
    }
    av_freep(&buf);
    avio_w8(tmp, 0);
    write_header_chunk(pb, tmp, tag);
    return 0;
  fail:
    av_free(buf);
    ffio_free_dyn_buf(&tmp);
    return ret;

#undef SKIP_DEFAULTS
#undef OPT_FLAGS_EXACT
#undef ENC
}
示例#20
0
static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags)
{
    OGGStreamContext *oggstream = (OGGStreamContext *)s->streams[page->stream_index]->priv_data;
    AVIOContext *pb;
    int64_t crc_offset;
    int ret, size;
    uint8_t *buf;

    ret = avio_open_dyn_buf(&pb);
    if (ret < 0)
        return ret;
    ffio_init_checksum(pb, ff_crc04C11DB7_update, 0);
    ffio_wfourcc(pb, (const uint8_t *)"OggS");
    avio_w8(pb, 0);
    avio_w8(pb, page->flags | extra_flags);
    avio_wl64(pb, page->granule);
    avio_wl32(pb, oggstream->serial_num);
    avio_wl32(pb, oggstream->page_counter++);
    crc_offset = avio_tell(pb);
    avio_wl32(pb, 0); // crc
    avio_w8(pb, page->segments_count);
    avio_write(pb, page->segments, page->segments_count);
    avio_write(pb, page->data, page->size);

    ogg_update_checksum(s, pb, crc_offset);
    avio_flush(pb);

    size = avio_close_dyn_buf(pb, &buf);
    if (size < 0)
        return size;

    avio_write(s->pb, buf, size);
    avio_flush(s->pb);
    av_free(buf);
    oggstream->page_count--;
    return 0;
}
示例#21
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);
}
示例#22
0
int ff_ape_write_tag(AVFormatContext *s)
{
    AVDictionaryEntry *e = NULL;
    int size, ret, count = 0;
    AVIOContext *dyn_bc = NULL;
    uint8_t *dyn_buf = NULL;

    if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
        goto end;

    // flags
    avio_wl32(dyn_bc, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER |
                     APE_TAG_FLAG_IS_HEADER);
    ffio_fill(dyn_bc, 0, 8);             // reserved

    ff_standardize_creation_time(s);
    while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) {
        int val_len;

        if (!string_is_ascii(e->key)) {
            av_log(s, AV_LOG_WARNING, "Non ASCII keys are not allowed\n");
            continue;
        }

        val_len = strlen(e->value);
        avio_wl32(dyn_bc, val_len);            // value length
        avio_wl32(dyn_bc, 0);                  // item flags
        avio_put_str(dyn_bc, e->key);          // key
        avio_write(dyn_bc, e->value, val_len); // value
        count++;
    }
    if (!count)
        goto end;

    size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
    if (size <= 0)
        goto end;
    size += 20;

    // header
    avio_write(s->pb, "APETAGEX", 8);   // id
    avio_wl32(s->pb, APE_TAG_VERSION);  // version
    avio_wl32(s->pb, size);
    avio_wl32(s->pb, count);

    avio_write(s->pb, dyn_buf, size - 20);

    // footer
    avio_write(s->pb, "APETAGEX", 8);   // id
    avio_wl32(s->pb, APE_TAG_VERSION);  // version
    avio_wl32(s->pb, size);             // size
    avio_wl32(s->pb, count);            // tag count

    // flags
    avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER);
    ffio_fill(s->pb, 0, 8);             // reserved

end:
    if (dyn_bc && !dyn_buf)
        avio_close_dyn_buf(dyn_bc, &dyn_buf);
    av_freep(&dyn_buf);

    return ret;
}
示例#23
0
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;
}
示例#24
0
int ff_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 (avio_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 + 1);
    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 = avio_close_dyn_buf(pb, &buf);
    if ((len > 0) && buf) {
        int av_unused result;
        av_dlog(s->ic, "sending %d bytes of RR\n", len);
        result = ffurl_write(s->rtp_ctx, buf, len);
        av_dlog(s->ic, "result from ffurl_write: %d\n", result);
        av_free(buf);
    }
    return 0;
}
示例#25
0
static int jpeg_parse_packet(AVFormatContext *ctx, PayloadContext *jpeg,
                             AVStream *st, AVPacket *pkt, uint32_t *timestamp,
                             const uint8_t *buf, int len, int flags)
{
    uint8_t type, q, width, height;
    const uint8_t *qtables = NULL;
    uint16_t qtable_len;
    uint32_t off;
    int ret;

    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;

    /* Parse the restart marker header. */
    if (type > 63) {
        av_log(ctx, AV_LOG_ERROR,
               "Unimplemented RTP/JPEG restart marker header.\n");
        return AVERROR_PATCHWELCOME;
    }

    /* Parse the quantization table header. */
    if (q > 127 && off == 0) {
        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 (q == 255 && qtable_len == 0) {
            av_log(ctx, AV_LOG_ERROR,
                   "Invalid RTP/JPEG packet. Quantization tables not found.\n");
            return AVERROR_INVALIDDATA;
        }

        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 (off == 0) {
        /* Start of JPEG data packet. */
        uint8_t new_qtables[128];
        uint8_t hdr[1024];

        /* 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;

        if (!qtables) {
            create_default_qtables(new_qtables, q);
            qtables    = new_qtables;
            qtable_len = sizeof(new_qtables);
        }

        /* 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 ? 2 : 1);

        /* 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. */
        PutBitContext pbc;
        uint8_t buf[2];

        /* Put EOI marker. */
        init_put_bits(&pbc, buf, sizeof(buf));
        put_marker(&pbc, EOI);
        flush_put_bits(&pbc);
        avio_write(jpeg->frame, buf, sizeof(buf));

        /* Prepare the JPEG packet. */
        av_init_packet(pkt);
        pkt->size = avio_close_dyn_buf(jpeg->frame, &pkt->data);
        if (pkt->size < 0) {
            av_log(ctx, AV_LOG_ERROR,
                   "Error occured when getting frame buffer.\n");
            jpeg->frame = NULL;
            return pkt->size;
        }
        pkt->stream_index = st->index;
        pkt->destruct     = av_destruct_packet;

        /* Re-init the frame buffer. */
        jpeg->frame = NULL;

        return 0;
    }

    return AVERROR(EAGAIN);
}
void FFMPEG_Wrapper::encode_frame(uint8_t *image_data, std::vector<uint8_t>& encoded_frame)
{

  boost::mutex::scoped_lock lock(frame_mutex_);

  avpicture_fill(ffmpeg_src_picture_, image_data,  (AVPixelFormat)CODING_FORMAT, input_width_,  input_height_);

  // get format conversion
  if (!ffmpeg_sws_ctx_) {
    static int sws_flags = SWS_BICUBIC;
      ffmpeg_sws_ctx_ = sws_getContext(input_width_, input_height_, (AVPixelFormat)CODING_FORMAT,
                                       output_width_, output_height_, ffmpeg_codec_context_->pix_fmt,
                                sws_flags, NULL, NULL, NULL);
      if (!ffmpeg_sws_ctx_) {
          fprintf(stderr,
                  "Could not initialize the conversion context\n");
          return;
      }
  }

  sws_scale(ffmpeg_sws_ctx_,
            (const uint8_t * const *)ffmpeg_src_picture_->data,
            ffmpeg_src_picture_->linesize, 0, input_height_, ffmpeg_dst_picture_->data, ffmpeg_dst_picture_->linesize);

  /* encode the image */
  AVPacket pkt;
  int got_output;

  av_init_packet(&pkt);
  pkt.data = NULL; // packet data will be allocated by the encoder
  pkt.size = 0;

  if (avcodec_encode_video2(ffmpeg_codec_context_, &pkt, ffmpeg_frame_, &got_output) < 0)
  {
    fprintf(stderr, "Error encoding video ffmpeg_frame_\n");
    return;
  }

  /* If size is zero, it means the image was buffered. */
  if (got_output)
  {
    std::size_t size;
    uint8_t* output_buf;

    if (ffmpeg_codec_context_->coded_frame->pts != AV_NOPTS_VALUE)
      pkt.pts = av_rescale_q(ffmpeg_codec_context_->coded_frame->pts, ffmpeg_codec_context_->time_base, ffmpeg_video_st_->time_base);

    pkt.pts= ffmpeg_codec_context_->coded_frame->pts;

    if (ffmpeg_codec_context_->coded_frame->key_frame)
      pkt.flags |= AV_PKT_FLAG_KEY;

    pkt.stream_index = ffmpeg_video_st_->index;

    if (avio_open_dyn_buf(&ffmpeg_format_context_->pb) >= 0)
     {
     ffmpeg_format_context_->pb->seekable = 0;

     if (av_write_frame(ffmpeg_format_context_, &pkt)) //av_write_frame
     {
     fprintf(stderr, "Error occurred when opening output file\n");
     return;
     }

     size = avio_close_dyn_buf(ffmpeg_format_context_->pb, &output_buf);

     encoded_frame.resize(size);
     memcpy(&encoded_frame[0], output_buf, size);

     av_free(output_buf);
     }
  }
  else
  {
    encoded_frame.clear();
  }

  av_free_packet(&pkt);

  AVRational timebase = ffmpeg_codec_context_->time_base;

  timebase.den += 2; //increased framerate to compensate playback delay

  //ffmpeg_frame_->pts++;
  ffmpeg_frame_->pts += av_rescale_q(1, timebase, ffmpeg_video_st_->time_base);
}
示例#27
0
/* write the header (used two times if non streamed) */
static int asf_write_header1(AVFormatContext *s, int64_t file_size,
                             int64_t data_chunk_size)
{
    ASFContext *asf = s->priv_data;
    AVIOContext *pb = s->pb;
    AVDictionaryEntry *tags[5];
    int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
    int has_title, has_aspect_ratio = 0;
    int metadata_count;
    AVCodecContext *enc;
    int64_t header_offset, cur_pos, hpos;
    int bit_rate;
    int64_t duration;

    ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);

    tags[0] = av_dict_get(s->metadata, "title", NULL, 0);
    tags[1] = av_dict_get(s->metadata, "author", NULL, 0);
    tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0);
    tags[3] = av_dict_get(s->metadata, "comment", NULL, 0);
    tags[4] = av_dict_get(s->metadata, "rating", NULL, 0);

    duration       = asf->duration + PREROLL_TIME * 10000;
    has_title      = tags[0] || tags[1] || tags[2] || tags[3] || tags[4];
    metadata_count = av_dict_count(s->metadata);

    bit_rate = 0;
    for (n = 0; n < s->nb_streams; n++) {
        enc = s->streams[n]->codec;

        avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */

        bit_rate += enc->bit_rate;
        if (   enc->codec_type == AVMEDIA_TYPE_VIDEO
            && enc->sample_aspect_ratio.num > 0
            && enc->sample_aspect_ratio.den > 0)
            has_aspect_ratio++;
    }

    if (asf->is_streamed) {
        put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
    }

    ff_put_guid(pb, &ff_asf_header);
    avio_wl64(pb, -1); /* header length, will be patched after */
    avio_wl32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 2); /* ??? */

    /* file header */
    header_offset = avio_tell(pb);
    hpos          = put_header(pb, &ff_asf_file_header);
    ff_put_guid(pb, &ff_asf_my_guid);
    avio_wl64(pb, file_size);
    file_time = 0;
    avio_wl64(pb, unix_to_file_time(file_time));
    avio_wl64(pb, asf->nb_packets); /* number of packets */
    avio_wl64(pb, duration); /* end time stamp (in 100ns units) */
    avio_wl64(pb, asf->duration); /* duration (in 100ns units) */
    avio_wl64(pb, PREROLL_TIME); /* start time stamp */
    avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2);  /* ??? */
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */
    end_header(pb, hpos);

    /* unknown headers */
    hpos = put_header(pb, &ff_asf_head1_guid);
    ff_put_guid(pb, &ff_asf_head2_guid);
    avio_wl16(pb, 6);
    if (has_aspect_ratio) {
        int64_t hpos2;
        avio_wl32(pb, 26 + has_aspect_ratio * 84);
        hpos2 = put_header(pb, &ff_asf_metadata_header);
        avio_wl16(pb, 2 * has_aspect_ratio);
        for (n = 0; n < s->nb_streams; n++) {
            enc = s->streams[n]->codec;
            if (   enc->codec_type == AVMEDIA_TYPE_VIDEO
                && enc->sample_aspect_ratio.num > 0
                && enc->sample_aspect_ratio.den > 0) {
                AVRational sar = enc->sample_aspect_ratio;
                avio_wl16(pb, 0);
                // the stream number is set like this below
                avio_wl16(pb, n + 1);
                avio_wl16(pb, 26); // name_len
                avio_wl16(pb,  3); // value_type
                avio_wl32(pb,  4); // value_len
                avio_put_str16le(pb, "AspectRatioX");
                avio_wl32(pb, sar.num);
                avio_wl16(pb, 0);
                // the stream number is set like this below
                avio_wl16(pb, n + 1);
                avio_wl16(pb, 26); // name_len
                avio_wl16(pb,  3); // value_type
                avio_wl32(pb,  4); // value_len
                avio_put_str16le(pb, "AspectRatioY");
                avio_wl32(pb, sar.den);
            }
        }
        end_header(pb, hpos2);
    } else {
        avio_wl32(pb, 0);
    }
    end_header(pb, hpos);

    /* title and other infos */
    if (has_title) {
        int len;
        uint8_t *buf;
        AVIOContext *dyn_buf;

        if (avio_open_dyn_buf(&dyn_buf) < 0)
            return AVERROR(ENOMEM);

        hpos = put_header(pb, &ff_asf_comment_header);

        for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) {
            len = tags[n] ? avio_put_str16le(dyn_buf, tags[n]->value) : 0;
            avio_wl16(pb, len);
        }
        len = avio_close_dyn_buf(dyn_buf, &buf);
        avio_write(pb, buf, len);
        av_freep(&buf);
        end_header(pb, hpos);
    }
    if (metadata_count) {
        AVDictionaryEntry *tag = NULL;
        hpos = put_header(pb, &ff_asf_extended_content_header);
        avio_wl16(pb, metadata_count);
        while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
            put_str16(pb, tag->key);
            avio_wl16(pb, 0);
            put_str16(pb, tag->value);
        }
        end_header(pb, hpos);
    }
    /* chapters using ASF markers */
    if (!asf->is_streamed && s->nb_chapters) {
        int ret;
        if (ret = asf_write_markers(s))
            return ret;
    }
    /* stream headers */
    for (n = 0; n < s->nb_streams; n++) {
        int64_t es_pos;
        //        ASFStream *stream = &asf->streams[n];

        enc                 = s->streams[n]->codec;
        asf->streams[n].num = n + 1;
        asf->streams[n].seq = 1;

        switch (enc->codec_type) {
        case AVMEDIA_TYPE_AUDIO:
            wav_extra_size = 0;
            extra_size     = 18 + wav_extra_size;
            extra_size2    = 8;
            break;
        default:
        case AVMEDIA_TYPE_VIDEO:
            wav_extra_size = enc->extradata_size;
            extra_size     = 0x33 + wav_extra_size;
            extra_size2    = 0;
            break;
        }

        hpos = put_header(pb, &ff_asf_stream_header);
        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
            ff_put_guid(pb, &ff_asf_audio_stream);
            ff_put_guid(pb, &ff_asf_audio_conceal_spread);
        } else {
            ff_put_guid(pb, &ff_asf_video_stream);
            ff_put_guid(pb, &ff_asf_video_conceal_none);
        }
        avio_wl64(pb, 0); /* ??? */
        es_pos = avio_tell(pb);
        avio_wl32(pb, extra_size); /* wav header len */
        avio_wl32(pb, extra_size2); /* additional data len */
        avio_wl16(pb, n + 1); /* stream number */
        avio_wl32(pb, 0); /* ??? */

        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
            /* WAVEFORMATEX header */
            int wavsize = ff_put_wav_header(pb, enc, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);

            if (wavsize < 0)
                return -1;
            if (wavsize != extra_size) {
                cur_pos = avio_tell(pb);
                avio_seek(pb, es_pos, SEEK_SET);
                avio_wl32(pb, wavsize); /* wav header len */
                avio_seek(pb, cur_pos, SEEK_SET);
            }
            /* ERROR Correction */
            avio_w8(pb, 0x01);
            if (enc->codec_id == AV_CODEC_ID_ADPCM_G726 || !enc->block_align) {
                avio_wl16(pb, 0x0190);
                avio_wl16(pb, 0x0190);
            } else {
                avio_wl16(pb, enc->block_align);
                avio_wl16(pb, enc->block_align);
            }
            avio_wl16(pb, 0x01);
            avio_w8(pb, 0x00);
        } else {
            avio_wl32(pb, enc->width);
            avio_wl32(pb, enc->height);
            avio_w8(pb, 2); /* ??? */
            avio_wl16(pb, 40 + enc->extradata_size); /* size */

            /* BITMAPINFOHEADER header */
            ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1, 0);
        }
        end_header(pb, hpos);
    }

    /* media comments */

    hpos = put_header(pb, &ff_asf_codec_comment_header);
    ff_put_guid(pb, &ff_asf_codec_comment1_header);
    avio_wl32(pb, s->nb_streams);
    for (n = 0; n < s->nb_streams; n++) {
        const AVCodecDescriptor *codec_desc;
        const char *desc;

        enc  = s->streams[n]->codec;
        codec_desc = avcodec_descriptor_get(enc->codec_id);

        if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
            avio_wl16(pb, 2);
        else if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
            avio_wl16(pb, 1);
        else
            avio_wl16(pb, -1);

        if (enc->codec_id == AV_CODEC_ID_WMAV2)
            desc = "Windows Media Audio V8";
        else
            desc = codec_desc ? codec_desc->name : NULL;

        if (desc) {
            AVIOContext *dyn_buf;
            uint8_t *buf;
            int len;

            if (avio_open_dyn_buf(&dyn_buf) < 0)
                return AVERROR(ENOMEM);

            avio_put_str16le(dyn_buf, desc);
            len = avio_close_dyn_buf(dyn_buf, &buf);
            avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2

            avio_write(pb, buf, len);
            av_freep(&buf);
        } else
            avio_wl16(pb, 0);

        avio_wl16(pb, 0); /* no parameters */

        /* id */
        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
            avio_wl16(pb, 2);
            avio_wl16(pb, enc->codec_tag);
        } else {
            avio_wl16(pb, 4);
            avio_wl32(pb, enc->codec_tag);
        }
        if (!enc->codec_tag)
            return -1;
    }
    end_header(pb, hpos);

    /* patch the header size fields */

    cur_pos     = avio_tell(pb);
    header_size = cur_pos - header_offset;
    if (asf->is_streamed) {
        header_size += 8 + 30 + DATA_HEADER_SIZE;

        avio_seek(pb, header_offset - 10 - 30, SEEK_SET);
        avio_wl16(pb, header_size);
        avio_seek(pb, header_offset - 2 - 30, SEEK_SET);
        avio_wl16(pb, header_size);

        header_size -= 8 + 30 + DATA_HEADER_SIZE;
    }
    header_size += 24 + 6;
    avio_seek(pb, header_offset - 14, SEEK_SET);
    avio_wl64(pb, header_size);
    avio_seek(pb, cur_pos, SEEK_SET);

    /* movie chunk, followed by packets of packet_size */
    asf->data_offset = cur_pos;
    ff_put_guid(pb, &ff_asf_data_header);
    avio_wl64(pb, data_chunk_size);
    ff_put_guid(pb, &ff_asf_my_guid);
    avio_wl64(pb, asf->nb_packets); /* nb packets */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 1); /* ??? */
    return 0;
}
/**
 * @return 0 when a packet was written into /p pkt, and no more data is left;
 *         1 when a packet was written into /p pkt, and more packets might be left;
 *        <0 when not enough data was provided to return a full packet, or on error.
 */
static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
                               AVStream *st, AVPacket *pkt,
                               uint32_t *timestamp,
                               const uint8_t *buf, int len, uint16_t seq,
                               int flags)
{
    AVIOContext *pb = &asf->pb;
    int res, mflags, len_off;
    RTSPState *rt = s->priv_data;

    if (!rt->asf_ctx)
        return -1;

    if (len > 0) {
        int off, out_len = 0;

        if (len < 4)
            return -1;

        av_freep(&asf->buf);

        ffio_init_context(pb, buf, len, 0, NULL, NULL, NULL, NULL);

        while (avio_tell(pb) + 4 < len) {
            int start_off = avio_tell(pb);

            mflags = avio_r8(pb);
            if (mflags & 0x80)
                flags |= RTP_FLAG_KEY;
            len_off = avio_rb24(pb);
            if (mflags & 0x20)   /**< relative timestamp */
                avio_skip(pb, 4);
            if (mflags & 0x10)   /**< has duration */
                avio_skip(pb, 4);
            if (mflags & 0x8)    /**< has location ID */
                avio_skip(pb, 4);
            off = avio_tell(pb);

            if (!(mflags & 0x40)) {
                /**
                 * If 0x40 is not set, the len_off field specifies an offset
                 * of this packet's payload data in the complete (reassembled)
                 * ASF packet. This is used to spread one ASF packet over
                 * multiple RTP packets.
                 */
                if (asf->pktbuf && len_off != avio_tell(asf->pktbuf)) {
                    uint8_t *p;
                    avio_close_dyn_buf(asf->pktbuf, &p);
                    asf->pktbuf = NULL;
                    av_free(p);
                }
                if (!len_off && !asf->pktbuf &&
                    (res = avio_open_dyn_buf(&asf->pktbuf)) < 0)
                    return res;
                if (!asf->pktbuf)
                    return AVERROR(EIO);

                avio_write(asf->pktbuf, buf + off, len - off);
                avio_skip(pb, len - off);
                if (!(flags & RTP_FLAG_MARKER))
                    return -1;
                out_len     = avio_close_dyn_buf(asf->pktbuf, &asf->buf);
                asf->pktbuf = NULL;
            } else {
                /**
                 * If 0x40 is set, the len_off field specifies the length of
                 * the next ASF packet that can be read from this payload
                 * data alone. This is commonly the same as the payload size,
                 * but could be less in case of packet splitting (i.e.
                 * multiple ASF packets in one RTP packet).
                 */

                int cur_len = start_off + len_off - off;
                int prev_len = out_len;
                out_len += cur_len;
                if (FFMIN(cur_len, len - off) < 0)
                    return -1;
                if ((res = av_reallocp(&asf->buf, out_len)) < 0)
                    return res;
                memcpy(asf->buf + prev_len, buf + off,
                       FFMIN(cur_len, len - off));
                avio_skip(pb, cur_len);
            }
        }

        init_packetizer(pb, asf->buf, out_len);
        pb->pos += rt->asf_pb_pos;
        pb->eof_reached = 0;
        rt->asf_ctx->pb = pb;
    }

    for (;;) {
        int i;

        res = ff_read_packet(rt->asf_ctx, pkt);
        rt->asf_pb_pos = avio_tell(pb);
        if (res != 0)
            break;
        for (i = 0; i < s->nb_streams; i++) {
            if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
                pkt->stream_index = i;
                return 1; // FIXME: return 0 if last packet
            }
        }
        av_free_packet(pkt);
    }

    return res == 1 ? -1 : res;
}
示例#29
0
/** 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);
}
示例#30
0
文件: mp3enc.c 项目: founderznd/libav
/*
 * 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;
}