Пример #1
0
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){

    dv_encode_full_frame(vf->priv->enc, mpi->planes, 
	(mpi->flags&MP_IMGFLAG_YUV) ? e_dv_color_yuv : e_dv_color_rgb,
	mux_v->buffer);

    muxer_write_chunk(mux_v, 480 * (vf->priv->enc->isPAL ? 300 : 250) , 0x10, pts, pts);
    return 1;
}
Пример #2
0
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
    long flags=0;
    int ret;
//    flip_upside_down(vo_image_ptr,vo_image_ptr,3*vo_w,vo_h); // dirty hack
    ret=vfw_encode_frame(mux_v->bih, mux_v->buffer, vfw_bih, mpi->planes[0], &flags, 10000);
//    if (ret != ICERR_OK)
//	return 0;
    muxer_write_chunk(mux_v,mux_v->bih->biSizeImage,flags, pts, pts);
    return 1;
}
Пример #3
0
static int encode_frame(struct vf_instance *vf, x264_picture_t *pic_in)
{
    h264_module_t *mod=(h264_module_t*)vf->priv;
    x264_picture_t pic_out;
    x264_nal_t *nal;
    int i_nal;
    int i_size;

    i_size = x264_encoder_encode(mod->x264, &nal, &i_nal, pic_in, &pic_out);

    if(i_size<0) {
        mp_msg(MSGT_MENCODER, MSGL_ERR, "x264_encoder_encode failed\n");
        return -1;
    }
    if(i_size>0) {
        int keyframe = pic_out.b_keyframe;
        memcpy(mod->mux->buffer, nal->p_payload, i_size);
        muxer_write_chunk(mod->mux, i_size, keyframe?AVIIF_KEYFRAME:0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
    }
    else
        ++mod->mux->encoder_delay;

    return i_size;
}
Пример #4
0
static int encode_frame(struct vf_instance_s* vf, AVFrame *pic, double pts){
    const char pict_type_char[5]= {'?', 'I', 'P', 'B', 'S'};
    int out_size;
    double dts;

    if(pts == MP_NOPTS_VALUE)
        pts= lavc_venc_context->frame_number * av_q2d(lavc_venc_context->time_base);

    if(pic){
#if 0
        pic->opaque= malloc(sizeof(pts));
        memcpy(pic->opaque, &pts, sizeof(pts));
#else
        if(pts != MP_NOPTS_VALUE)
            pic->pts= floor(pts / av_q2d(lavc_venc_context->time_base) + 0.5);
        else
            pic->pts= MP_NOPTS_VALUE;
#endif
    }
	out_size = avcodec_encode_video(lavc_venc_context, mux_v->buffer, mux_v->buffer_size,
	    pic);

    if(pts != MP_NOPTS_VALUE) 
        dts= pts - lavc_venc_context->delay * av_q2d(lavc_venc_context->time_base);
    else
        dts= MP_NOPTS_VALUE;
#if 0
    pts= lavc_venc_context->coded_frame->opaque ?
           *(double*)lavc_venc_context->coded_frame->opaque
         : MP_NOPTS_VALUE;
#else
    if(lavc_venc_context->coded_frame->pts != MP_NOPTS_VALUE)
        pts= lavc_venc_context->coded_frame->pts * av_q2d(lavc_venc_context->time_base);
    else
        pts= MP_NOPTS_VALUE;
    assert(MP_NOPTS_VALUE == AV_NOPTS_VALUE);
#endif
//fprintf(stderr, "ve_lavc %f/%f\n", dts, pts);
    if(out_size == 0 && lavc_param_skip_threshold==0 && lavc_param_skip_factor==0){
        ++mux_v->encoder_delay;
        return 0;
    }
           
    muxer_write_chunk(mux_v,out_size,lavc_venc_context->coded_frame->key_frame?0x10:0, 
                      dts, pts);
    free(lavc_venc_context->coded_frame->opaque);
    lavc_venc_context->coded_frame->opaque= NULL;
        
    /* store psnr / pict size / type / qscale */
    if(lavc_param_psnr){
        static FILE *fvstats=NULL;
        char filename[20];
        double f= lavc_venc_context->width*lavc_venc_context->height*255.0*255.0;
	double quality=0.0;
	int8_t *q;

        if(!fvstats) {
            time_t today2;
            struct tm *today;
            today2 = time(NULL);
            today = localtime(&today2);
            sprintf(filename, "psnr_%02d%02d%02d.log", today->tm_hour,
                today->tm_min, today->tm_sec);
            fvstats = fopen(filename,"w");
            if(!fvstats) {
                perror("fopen");
                lavc_param_psnr=0; // disable block
                mp_msg(MSGT_MENCODER,MSGL_ERR,"Can't open %s for writing. Check its permissions.\n",filename);
                return -1;
                /*exit(1);*/
            }
        }
	
	// average MB quantizer
	q = lavc_venc_context->coded_frame->qscale_table;
	if(q) {
	    int x, y;
	    int w = (lavc_venc_context->width+15) >> 4;
	    int h = (lavc_venc_context->height+15) >> 4;
	    for( y = 0; y < h; y++ ) {
		for( x = 0; x < w; x++ )
		    quality += (double)*(q+x);
		q += lavc_venc_context->coded_frame->qstride;
	    }
	    quality /= w * h;
	} else 
	    quality = lavc_venc_context->coded_frame->quality / (float)FF_QP2LAMBDA;

        fprintf(fvstats, "%6d, %2.2f, %6d, %2.2f, %2.2f, %2.2f, %2.2f %c\n",
            lavc_venc_context->coded_frame->coded_picture_number,
            quality,
            out_size,
            psnr(lavc_venc_context->coded_frame->error[0]/f),
            psnr(lavc_venc_context->coded_frame->error[1]*4/f),
            psnr(lavc_venc_context->coded_frame->error[2]*4/f),
            psnr((lavc_venc_context->coded_frame->error[0]+lavc_venc_context->coded_frame->error[1]+lavc_venc_context->coded_frame->error[2])/(f*1.5)),
            pict_type_char[lavc_venc_context->coded_frame->pict_type]
            );
    }
Пример #5
0
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){

    OSErr cres;
    long framesizemax;
    UInt8 similarity=0;
    long compressedsize;
    OSType in_format=kYUVSPixelFormat;
    int width = mpi->width;
    int height = mpi->height;
    int stride = width*2;
if(!codec_initialized){
    FrameRect.top=0;
    FrameRect.left=0;
    FrameRect.right=width;
    FrameRect.bottom=height;
    cres = QTNewGWorldFromPtr(
        &frame_GWorld_in,
        in_format,
        &FrameRect,
        0,
        0,
        0,
        mpi->planes[0],
        stride);
    mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
    //dunno what todo about this
    frame_prev = malloc(stride * height);
    cres = QTNewGWorldFromPtr(
        &frame_GWorld_prev,
        in_format,
        &FrameRect,
        0,
        0,
        0,
        frame_prev,
        stride);
    mp_msg(MSGT_MENCODER,MSGL_DBG2,"height:%i width:%i stride:%i\n",height,width,stride);
    mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
    cres=  GetMaxCompressionSize (
       GetGWorldPixMap(frame_GWorld_in),
       &FrameRect,
       24,
       codecNormalQuality,
       bswap_32(format),
       compressor,
       &framesizemax );
    mp_msg(MSGT_MENCODER,MSGL_DBG2,"GetMaxCompressionSize returned:%i : MaxSize:%li\n",cres&0xFFFF,framesizemax);
    frame_comp=malloc(framesizemax);

    desc = (ImageDescriptionHandle)NewHandleClear(MAX_IDSIZE); //memory where the desc will be stored
    (*desc)->idSize=MAX_IDSIZE;

    cres= CompressSequenceBegin (
       &seq,
       GetGWorldPixMap( frame_GWorld_in),
       GetGWorldPixMap( frame_GWorld_prev),
       &FrameRect,
       &FrameRect,
       24, // color depth
       bswap_32(format), // fourcc
       compressor,  // codec component
       codecNormalQuality, //codecNormalQuality,
       codecMaxQuality, //codecNormalQuality,
       10*30, // keyframe rate
       0,
       0,
       desc);
    mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceBegin returned:%i\n",cres&0xFFFF);
    mp_msg(MSGT_MENCODER,MSGL_DBG2,"Sequence ID:%i\n",seq);

    if (mp_msg_test(MSGT_MENCODER, MSGL_DBG2))
        dump_ImageDescription(*desc);
    codec_initialized++;
}
    cres = CompressSequenceFrame (
    	seq,
        GetGWorldPixMap(frame_GWorld_in),
        &FrameRect,
        0,
        (char*)mux_v->buffer,
        &compressedsize,
        &similarity,
        0);

    if(cres&0xFFFF)mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceFrame returned:%i\n",cres&0xFFFF);
#if 0
    printf("Size %i->%i   \n",stride*height,compressedsize);
    printf("Ratio: %i:1\n",(stride*height)/compressedsize);
#endif
    muxer_write_chunk(mux_v, compressedsize , similarity?0:0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);

    if(((*desc)->idSize)>MAX_IDSIZE){
	mp_msg(MSGT_MENCODER,MSGL_ERR,"FATAL! idSize=%d too big, increase MAX_IDSIZE in ve_qtvideo.c!\n",((*desc)->idSize));
    } else {
	// according to QT docs, imagedescription may be changed while encoding
	// a frame (even its size may (and does!) change!)
	memcpy(mux_v->bih+1,*desc,(*desc)->idSize);
    }

    return 1;
}
Пример #6
0
static int encode_frame(struct vf_instance *vf, AVFrame *pic, double pts){
    const char pict_type_char[5]= {'?', 'I', 'P', 'B', 'S'};
    double dts;
    AVPacket pkt;
    int res, got_pkt;

    if(pts == MP_NOPTS_VALUE)
        pts= lavc_venc_context->frame_number * av_q2d(lavc_venc_context->time_base);

    if(pic){
#if 0
        pic->opaque= malloc(sizeof(pts));
        memcpy(pic->opaque, &pts, sizeof(pts));
#else
        if(pts != MP_NOPTS_VALUE)
            pic->pts= floor(pts / av_q2d(lavc_venc_context->time_base) + 0.5);
        else
            pic->pts= MP_NOPTS_VALUE;
#endif
    }
    av_init_packet(&pkt);
    pkt.data = mux_v->buffer;
    pkt.size = mux_v->buffer_size;
    res = avcodec_encode_video2(lavc_venc_context, &pkt, pic, &got_pkt);

    /* store stats if there are any */
    if(lavc_venc_context->stats_out && stats_file) {
        fprintf(stats_file, "%s", lavc_venc_context->stats_out);
        /* make sure we can't accidentally store the same stats twice */
        lavc_venc_context->stats_out[0] = 0;
    }

    if (res < 0)
        return 0;
    if(!got_pkt && lavc_param_skip_threshold==0 && lavc_param_skip_factor==0){
        ++mux_v->encoder_delay;
        return 0;
    }

    dts = pts = MP_NOPTS_VALUE;
    if (pkt.pts != AV_NOPTS_VALUE)
        pts = pkt.pts * av_q2d(lavc_venc_context->time_base);
    if (pkt.dts != AV_NOPTS_VALUE)
        dts = pkt.dts * av_q2d(lavc_venc_context->time_base);

    muxer_write_chunk(mux_v,pkt.size,pkt.flags & AV_PKT_FLAG_KEY ?0x10:0,
                      dts, pts);

    /* store psnr / pict size / type / qscale */
    if(lavc_param_psnr){
        static FILE *fvstats=NULL;
        char filename[20];
        double f= lavc_venc_context->width*lavc_venc_context->height*255.0*255.0;
	double quality=0.0;
	int8_t *q;

        if(!fvstats) {
            time_t today2;
            struct tm *today;
            today2 = time(NULL);
            today = localtime(&today2);
            sprintf(filename, "psnr_%02d%02d%02d.log", today->tm_hour,
                today->tm_min, today->tm_sec);
            fvstats = fopen(filename,"w");
            if(!fvstats) {
                perror("fopen");
                lavc_param_psnr=0; // disable block
                mp_msg(MSGT_MENCODER,MSGL_ERR,"Can't open %s for writing. Check its permissions.\n",filename);
                return -1;
                /*exit(1);*/
            }
        }

	// average MB quantizer
	q = lavc_venc_context->coded_frame->qscale_table;
	if(q) {
	    int x, y;
	    int w = (lavc_venc_context->width+15) >> 4;
	    int h = (lavc_venc_context->height+15) >> 4;
	    for( y = 0; y < h; y++ ) {
		for( x = 0; x < w; x++ )
		    quality += (double)*(q+x);
		q += lavc_venc_context->coded_frame->qstride;
	    }
	    quality /= w * h;
	} else
	    quality = lavc_venc_context->coded_frame->quality / (float)FF_QP2LAMBDA;

        fprintf(fvstats, "%6d, %2.2f, %6d, %2.2f, %2.2f, %2.2f, %2.2f %c\n",
            lavc_venc_context->coded_frame->coded_picture_number,
            quality,
            pkt.size,
            psnr(lavc_venc_context->coded_frame->error[0]/f),
            psnr(lavc_venc_context->coded_frame->error[1]*4/f),
            psnr(lavc_venc_context->coded_frame->error[2]*4/f),
            psnr((lavc_venc_context->coded_frame->error[0]+lavc_venc_context->coded_frame->error[1]+lavc_venc_context->coded_frame->error[2])/(f*1.5)),
            pict_type_char[lavc_venc_context->coded_frame->pict_type]
            );
    }
Пример #7
0
static int put_image(struct vf_instance_s *vf, mp_image_t *mpi, double pts) {
    mux_v->buffer = mpi->planes[0];
    muxer_write_chunk(mux_v, mpi->width*mpi->height*mux_v->bih->biBitCount/8, 0x10, pts, pts);
    return 1;
}
Пример #8
0
int main(int argc,char ** argv){
int c;
FILE *f;
FILE *f2;
muxer_t* avi;
muxer_stream_t* mux;
//unsigned char* buffer=malloc(0x200000);
int i,len;
int v_id=0;
int flag2=0;
int prefix=0;

// check if enough args were given
if ( argc < 3 ){
    printf("Too few arguments given!\n"
           "Usage: %s <input_file> <output_file>\n", argv[0]);

    return -1;
}
// input
if(!(f=fopen(argv[1],"rb"))){
       printf("Couldn't open input file.\n");
       return -1;
}
// output
if(!(f2=fopen(argv[2],"wb"))){
       printf("Couldn't open output file.\n");
       return -1;
}

avi=muxer_new_muxer(MUXER_TYPE_AVI,f2);
mux=muxer_new_stream(avi,MUXER_TYPE_VIDEO);

mux->buffer_size=0x200000;
mux->buffer=malloc(mux->buffer_size);

mux->h.dwScale=1;
mux->h.dwRate=10;

mux->bih=malloc(sizeof(*mux->bih));
mux->bih->biSize=sizeof(*mux->bih);
mux->bih->biPlanes=1;
mux->bih->biBitCount=24;
mux->bih->biCompression=0x6f766976;//      7669766f;
muxer_write_header(avi);

/*
c=fgetc(f); if(c) printf("error! not vivo file?\n");
len=0;
while((c=fgetc(f))>=0x80) len+=0x80*(c&0x0F);
len+=c;
printf("hdr1: %d\n",len);
for(i=0;i<len;i++) fgetc(f);
*/

while((c=fgetc(f))>=0){

    printf("%08lX  %02X\n",ftell(f),c);

    prefix=0;
    if(c==0x82){
	prefix=1;
	//continue;
	c=fgetc(f);
	printf("%08lX  %02X\n",ftell(f),c);
    }

    if(c==0x00){
	// header
	int len=0;
	while((c=fgetc(f))>=0x80) len+=0x80*(c&0x0F);
	len+=c;
	printf("header: 00 (%d)\n",len);
	for(i=0;i<len;i++) fgetc(f);
	continue;
    }

    if((c&0xF0)==0x40){
	// audio
	len=24;
	if(prefix) len=fgetc(f);
	printf("audio: %02X (%d)\n",c,len);
	for(i=0;i<len;i++) fgetc(f);
	continue;
    }
    if((c&0xF0)==0x30){
	// audio
	len=40;
	if(prefix) len=fgetc(f);
	printf("audio: %02X (%d)\n",c,len);
	for(i=0;i<len;i++) fgetc(f);
	continue;
    }
    if(flag2 || (((c&0xF0)==0x10 || (c&0xF0)==0x20) && (c&0x0F)!=(v_id&0xF))){
	// end of frame:
	printf("Frame size: %d\n",mux->buffer_len);
	h263_decode_picture_header(mux->buffer);
	muxer_write_chunk(mux,mux->buffer_len,0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
	mux->buffer_len=0;

	if((v_id&0xF0)==0x10) fprintf(stderr,"hmm. last video packet %02X\n",v_id);
    }
    flag2=0;
    if((c&0xF0)==0x10){
	// 128 byte
	len=128;
	if(prefix) len=fgetc(f);
	printf("video: %02X (%d)\n",c,len);
	fread(mux->buffer+mux->buffer_len,len,1,f);
	mux->buffer_len+=len;
    v_id=c;
	continue;
    }
    if((c&0xF0)==0x20){
	int len=fgetc(f);
	printf("video: %02X (%d)\n",c,len);
	fread(mux->buffer+mux->buffer_len,len,1,f);
	mux->buffer_len+=len;
	flag2=1;
    v_id=c;
	continue;
    }
    printf("error: %02X!\n",c);
    exit(1);
}

if(!width) width=320;
if(!height) height=240;

mux->bih->biWidth=width;
mux->bih->biHeight=height;
mux->bih->biSizeImage=3*width*height;

muxer_write_index(avi);
fseek(f2,0,SEEK_SET);
muxer_write_header(avi);

return 0;
}
Пример #9
0
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
  struct rtframeheader* ench = (struct rtframeheader*)vf->priv->buffer;
  uint8_t* data = vf->priv->buffer + FRAMEHEADERSIZE;
  uint8_t* zdata = vf->priv->zbuffer + FRAMEHEADERSIZE;
  int len = 0, zlen = 0,r;

  memset(vf->priv->buffer,0,FRAMEHEADERSIZE); // Reset the header
  if(vf->priv->lzo)
    memset(vf->priv->zbuffer,0,FRAMEHEADERSIZE);
    
  // This has to be don here otherwise tv with sound doesn't work
  if(!vf->priv->tbl_wrote) {    
    RTjpeg_init_compress((long int*)data,mpi->width,mpi->height,vf->priv->q);
    RTjpeg_init_mcompress();

    ench->frametype = 'D'; // compressor data
    ench->comptype  = 'R'; // compressor data for RTjpeg
    ench->packetlength = 128*sizeof(long int);
  
    le2me_rtframeheader(ench);
    mux_v->buffer=vf->priv->buffer;
    muxer_write_chunk(mux_v,FRAMEHEADERSIZE + 128*sizeof(long int), 0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
    vf->priv->tbl_wrote = 1;
    memset(ench,0,FRAMEHEADERSIZE); // Reset the header
  }

  // Raw picture
  if(vf->priv->raw) {
    len = mpi->width*mpi->height*3/2;
    // Try lzo ???
    if(vf->priv->lzo) {
      r = lzo1x_1_compress(mpi->planes[0],mpi->width*mpi->height*3/2,
			   zdata,&zlen,vf->priv->zmem);
      if(r != LZO_E_OK) {
	mp_msg(MSGT_VFILTER,MSGL_ERR,"LZO compress error\n");
	zlen = 0;
      }
    }

    if(zlen <= 0 || zlen > len) {
      memcpy(data,mpi->planes[0],len);
      ench->comptype = '0';
    } else { // Use lzo only if it's littler
      ench = (struct rtframeheader*)vf->priv->zbuffer;
      ench->comptype = '3';
      len = zlen;
    }

  } else { // RTjpeg compression
    len = RTjpeg_mcompressYUV420(data,mpi->planes[0],vf->priv->l,
				 vf->priv->c);
    if(len <= 0) {
      mp_msg(MSGT_VFILTER,MSGL_ERR,"RTjpeg_mcompressYUV420 error (%d)\n",len);
      return 0;
    }

    if(vf->priv->lzo) {
      r = lzo1x_1_compress(data,len,zdata,&zlen,vf->priv->zmem);
      if(r != LZO_E_OK) {
	mp_msg(MSGT_VFILTER,MSGL_ERR,"LZO compress error\n");
	zlen = 0;
      }
    }

    if(zlen <= 0 || zlen > len)
      ench->comptype = '1';
    else {
      ench = (struct rtframeheader*)vf->priv->zbuffer;
      ench->comptype = '2';
      len = zlen;
    }

  }
    
  ench->frametype = 'V'; // video frame
  ench->packetlength = len;
  le2me_rtframeheader(ench);
  mux_v->buffer=(void*)ench;
  muxer_write_chunk(mux_v, len + FRAMEHEADERSIZE, 0x10, pts, pts);
  return 1;
}
Пример #10
0
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
  uint8_t *header  = vf->priv->buffer;
  uint8_t* data = vf->priv->buffer + FRAMEHEADERSIZE;
  uint8_t* zdata = vf->priv->zbuffer + FRAMEHEADERSIZE;
  int len = 0, r;
  size_t zlen = 0;

  memset(header, 0, FRAMEHEADERSIZE); // Reset the header
  if(vf->priv->lzo)
    memset(vf->priv->zbuffer,0,FRAMEHEADERSIZE);

  // This has to be don here otherwise tv with sound doesn't work
  if(!vf->priv->tbl_wrote) {
    RTjpeg_init_compress((uint32_t *)data,mpi->width,mpi->height,vf->priv->q);
    RTjpeg_init_mcompress();

    header[0] = 'D'; // frametype: compressor data
    header[1] = 'R'; // comptype:  compressor data for RTjpeg
    AV_WL32(header + 8, COMPDATASIZE); // packetlength

    mux_v->buffer=vf->priv->buffer;
    muxer_write_chunk(mux_v,FRAMEHEADERSIZE + COMPDATASIZE, 0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
    vf->priv->tbl_wrote = 1;
    memset(header, 0, FRAMEHEADERSIZE); // Reset the header
  }

  // Raw picture
  if(vf->priv->raw) {
    len = mpi->width*mpi->height*3/2;
    // Try lzo ???
    if(vf->priv->lzo) {
      r = lzo1x_1_compress(mpi->planes[0],len,
			   zdata,&zlen,vf->priv->zmem);
      if(r != LZO_E_OK) {
	mp_msg(MSGT_VFILTER,MSGL_ERR,"LZO compress error\n");
	zlen = 0;
      }
    }

    if(zlen <= 0 || zlen > len) {
      memcpy(data,mpi->planes[0],len);
      header[1] = '0'; // comptype: uncompressed
    } else { // Use lzo only if it's littler
      header = vf->priv->zbuffer;
      header[1] = '3'; //comptype: lzo
      len = zlen;
    }

  } else { // RTjpeg compression
    len = RTjpeg_mcompressYUV420(data,mpi->planes[0],vf->priv->l,
				 vf->priv->c);
    if(len <= 0) {
      mp_msg(MSGT_VFILTER,MSGL_ERR,"RTjpeg_mcompressYUV420 error (%d)\n",len);
      return 0;
    }

    if(vf->priv->lzo) {
      r = lzo1x_1_compress(data,len,zdata,&zlen,vf->priv->zmem);
      if(r != LZO_E_OK) {
	mp_msg(MSGT_VFILTER,MSGL_ERR,"LZO compress error\n");
	zlen = 0;
      }
    }

    if(zlen <= 0 || zlen > len)
      header[1] = '1'; // comptype: RTjpeg
    else {
      header = vf->priv->zbuffer;
      header[1] = '2'; // comptype: RTjpeg + LZO
      len = zlen;
    }

  }

  header[0] = 'V'; // frametype: video frame
  AV_WL32(header + 8, len); // packetlength
  mux_v->buffer = header;
  muxer_write_chunk(mux_v, len + FRAMEHEADERSIZE, 0x10, pts, pts);
  return 1;
}