Exemplo n.º 1
0
/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;

    if( p_dec->fmt_in.i_codec != VLC_CODEC_THEORA )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
        return VLC_ENOMEM;
    p_dec->p_sys->b_packetizer = false;
    p_sys->b_has_headers = false;
    p_sys->i_pts = VLC_TS_INVALID;
    p_sys->b_decoded_first_keyframe = false;

    /* Set output properties */
    p_dec->fmt_out.i_cat = VIDEO_ES;
    p_dec->fmt_out.i_codec = VLC_CODEC_I420;

    /* Set callbacks */
    p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
        DecodeBlock;
    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
        DecodeBlock;

    /* Init supporting Theora structures needed in header parsing */
    theora_comment_init( &p_sys->tc );
    theora_info_init( &p_sys->ti );

    return VLC_SUCCESS;
}
Exemplo n.º 2
0
static void enc_init(MSFilter *f){
	EncState *s=(EncState *)ms_new(EncState,1);
	theora_info_init(&s->tinfo);
	s->tinfo.width=MS_VIDEO_SIZE_CIF_W;
	s->tinfo.height=MS_VIDEO_SIZE_CIF_H;
	s->tinfo.frame_width=MS_VIDEO_SIZE_CIF_W;
	s->tinfo.frame_height=MS_VIDEO_SIZE_CIF_H;
	s->tinfo.offset_x=0;
	s->tinfo.offset_y=0;
	s->tinfo.target_bitrate=500000;
	s->tinfo.pixelformat=OC_PF_420;
	s->tinfo.fps_numerator=15;
	s->tinfo.fps_denominator=1;
	s->tinfo.aspect_numerator=1;
	s->tinfo.aspect_denominator=1;
	s->tinfo.colorspace=OC_CS_UNSPECIFIED;
	s->tinfo.dropframes_p=0;
	s->tinfo.quick_p=1;
	s->tinfo.quality=63;
	s->tinfo.keyframe_auto_p=1;
	s->tinfo.keyframe_frequency=64;
	s->tinfo.keyframe_frequency_force=64;
	s->tinfo.keyframe_data_target_bitrate=s->tinfo.target_bitrate*1.2;
	s->tinfo.keyframe_auto_threshold=80;
	s->tinfo.keyframe_mindistance=8;
	s->tinfo.noise_sensitivity=1;
	s->packed_conf=NULL;
	s->start_time=0;
	s->conf_time=0;
	s->mtu=ms_get_payload_max_size()-6;
	s->nframes=0;
	f->data=s;
}
Exemplo n.º 3
0
static int
noop_test_encode ()
{
  theora_info ti;
  theora_state th;

  INFO ("+ Initializing theora_info struct");
  theora_info_init (&ti);

  INFO ("+ Setting a 16x16 frame");
  ti.width = 16;
  ti.height = 16;

  INFO ("+ Setting a 1:1 frame rate");
  ti.fps_numerator = 1;
  ti.fps_denominator = 1;

  INFO ("+ Initializing theora_state for encoding");
  if (theora_encode_init (&th, &ti) != OC_DISABLED) {
    INFO ("+ Clearing theora_state");
    theora_clear (&th);
  }

  INFO ("+ Clearing theora_info struct");
  theora_info_clear (&ti);

  return 0;
}
Exemplo n.º 4
0
Arquivo: file.c Projeto: Garalv/miumiu
int read_cb(OGGZ *oggz, ogg_packet *op, long serialno, void *data)
{
	struct theora_headers *th;

	const char theoraId[] = "\x80theora";
	const char speexId[] = "Speex   ";

	if ( memcmp(op->packet, theoraId, strlen(theoraId)) == 0 )
	{
		//mylog("Detected a Theora stream with serialno=%d\n", serialno);
		oggz_set_read_callback(oggz, serialno, read_theora_cb, NULL);
		video_stream->serialno = serialno;

		// Initialize theora specific data fields
		th = (struct theora_headers *)calloc(1, sizeof(struct theora_headers));
		theora_info_init(&(th->ti));
		theora_comment_init(&(th->tc));
		video_stream->data = th;

		read_theora_cb(oggz, op, serialno, data);
	} else if ( memcmp(op->packet, speexId, strlen(speexId)) == 0 )
	{
		//mylog("Detected a Speex stream with serialno=%d\n", serialno);
		oggz_set_read_callback(oggz, serialno, read_speex_cb, NULL);
		audio_stream->serialno = serialno;
		read_speex_cb(oggz, op, serialno, data);
	} else
	{
		mylog("Got unknown ogg packet, serialno=%d, size=%d, packetno=%d, granulepos=%d\n",
				serialno, op->bytes, op->packetno, op->granulepos);
	}
	return 0;
}
Exemplo n.º 5
0
static void dec_init(MSFilter *f){
	DecState *s=(DecState *)ms_new(DecState,1);
	s->ready=FALSE;
	theora_info_init(&s->tinfo);
	s->yuv=NULL;
	s->curframe=NULL;
	f->data=s;
}
Exemplo n.º 6
0
static GstStateChangeReturn
theora_enc_change_state (GstElement * element, GstStateChange transition)
{
  GstTheoraEnc *enc;
  GstStateChangeReturn ret;

  enc = GST_THEORA_ENC (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state");
      theora_info_init (&enc->info);
      theora_comment_init (&enc->comment);
      enc->packetno = 0;
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      break;
    default:
      break;
  }

  ret = parent_class->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state");
      theora_clear (&enc->state);
      theora_comment_clear (&enc->comment);
      theora_info_clear (&enc->info);

      theora_enc_clear (enc);
      enc->initialised = FALSE;
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      break;
    default:
      break;
  }

  return ret;
}
Exemplo n.º 7
0
bool Oggeyman::init(const char * path) {

	switch (video_format) {
	//pixel_format.set(r_offset,g_offset,b_offset,bpp not a_offset);
	case VF_RGB:
		pixel_format.set(0, 1, 2, 3);
		break;
	case VF_BGR:
		pixel_format.set(2, 1, 0, 3);
		break;
	case VF_RGBA:
		pixel_format.set(0, 1, 2, 4);
		break;
	case VF_BGRA:
		pixel_format.set(2, 1, 0, 4);
		break;
	}
	this->path = path;
	// open the input file
	infptr = fopen(path, "rb");
	if (!infptr) {
		printf("\t failure opening %s\n", path);
		return false;
	}
	// initialize  ogg and theora -- none of these have a useful diagnostics implemented
	ogg_sync_init(&overall_sync_state);
	theora_info_init(&theo_info);
	theora_comment_init(&theo_comment);
	// find theora stream
	if (!parse_headers())	return false;
	// bcs we are only interested in theora,
	// flip through pages until we are sure we are on theora page
	bool have_page = false;
	bool is_theora_page = false;
	do { // we start by checking the page that was read in during header perusal
		int retval = ogg_stream_pagein(&ogg_theora_stream_state, &current_ogg_page);
		is_theora_page = (retval >= 0);
		if (!is_theora_page) have_page = next_page();
	} while (have_page && !is_theora_page);
	// initialize theora decoder
	if (!initialize_theora())
		return false;
	// the user should allocate space for the output buffer, BGRAbuffer
	return true;
}
Exemplo n.º 8
0
static int
noop_test_decode ()
{
  theora_info ti;
  theora_state th;

  INFO ("+ Initializing theora_info struct");
  theora_info_init (&ti);

  INFO ("+ Initializing theora_state for decoding");
  theora_decode_init (&th, &ti);

  INFO ("+ Clearing theora_state");
  theora_clear (&th);

  INFO ("+ Clearing theora_info struct");
  theora_info_clear (&ti);

  return 0;
}
Exemplo n.º 9
0
static int
noop_test_encode ()
{
  theora_info ti;
  theora_state th;

  INFO ("+ Initializing theora_info struct");
  theora_info_init (&ti);

  INFO ("+ Initializing theora_state for encoding");
  if (theora_encode_init (&th, &ti) != OC_DISABLED) {
    INFO ("+ Clearing theora_state");
    theora_clear (&th);
  }

  INFO ("+ Clearing theora_info struct");
  theora_info_clear (&ti);

  return 0;
}
Exemplo n.º 10
0
static GstStateChangeReturn
theora_dec_change_state (GstElement * element, GstStateChange transition)
{
  GstTheoraDec *dec = GST_THEORA_DEC (element);
  GstStateChangeReturn ret;

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      theora_info_init (&dec->info);
      theora_comment_init (&dec->comment);
      GST_DEBUG_OBJECT (dec, "Setting have_header to FALSE in READY->PAUSED");
      dec->have_header = FALSE;
      gst_theora_dec_reset (dec);
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      break;
    default:
      break;
  }

  ret = parent_class->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      theora_clear (&dec->state);
      theora_comment_clear (&dec->comment);
      theora_info_clear (&dec->info);
      gst_theora_dec_reset (dec);
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      break;
    default:
      break;
  }

  return ret;
}
Exemplo n.º 11
0
/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;

    if( p_dec->fmt_in.i_codec != VLC_FOURCC('t','h','e','o') )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys =
          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
    {
        msg_Err( p_dec, "out of memory" );
        return VLC_EGENERIC;
    }
    p_dec->p_sys->b_packetizer = VLC_FALSE;

    p_sys->i_pts = 0;
    p_sys->b_decoded_first_keyframe = VLC_FALSE;

    /* Set output properties */
    p_dec->fmt_out.i_cat = VIDEO_ES;
    p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');

    /* Set callbacks */
    p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
        DecodeBlock;
    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
        DecodeBlock;

    /* Init supporting Theora structures needed in header parsing */
    theora_comment_init( &p_sys->tc );
    theora_info_init( &p_sys->ti );

    p_sys->i_headers = 0;

    return VLC_SUCCESS;
}
Exemplo n.º 12
0
static GF_Err THEO_AttachStream(GF_BaseDecoder *ifcg, u16 ES_ID, char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool UpStream)
{
    ogg_packet oggpacket;
	GF_BitStream *bs;

	THEORACTX();
	if (ctx->ES_ID) return GF_BAD_PARAM;
	
	if (!decSpecInfo) return GF_NON_COMPLIANT_BITSTREAM;

	if (objectTypeIndication != GPAC_OGG_MEDIA_OTI) return GF_NON_COMPLIANT_BITSTREAM;
	if ( (decSpecInfoSize<9) || strncmp(&decSpecInfo[3], "theora", 6)) return GF_NON_COMPLIANT_BITSTREAM;

	oggpacket.granulepos = -1;
	oggpacket.b_o_s = 1;
	oggpacket.e_o_s = 0;
	oggpacket.packetno = 0;

	ctx->ES_ID = ES_ID;

    theora_info_init(&ctx->ti);
    theora_comment_init(&ctx->tc);


	bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ);
	while (gf_bs_available(bs)) {
		oggpacket.bytes = gf_bs_read_u16(bs);
		oggpacket.packet = malloc(sizeof(char) * oggpacket.bytes);
		gf_bs_read_data(bs, oggpacket.packet, oggpacket.bytes);
		if (theora_decode_header(&ctx->ti, &ctx->tc, &oggpacket) < 0 ) {
			free(oggpacket.packet);
			gf_bs_del(bs);
			return GF_NON_COMPLIANT_BITSTREAM;
		}
		free(oggpacket.packet);
	}
    theora_decode_init(&ctx->td, &ctx->ti);
	gf_bs_del(bs);
	return GF_OK;
}
Exemplo n.º 13
0
static int encode_init(AVCodecContext* avc_context)
{
    theora_info t_info;
    theora_comment t_comment;
    ogg_packet o_packet;
    unsigned int offset;
    TheoraContext *h = avc_context->priv_data;

    /* Set up the theora_info struct */
    theora_info_init( &t_info );
    t_info.width = avc_context->width;
    t_info.height = avc_context->height;
    t_info.frame_width = avc_context->width;
    t_info.frame_height = avc_context->height;
    t_info.offset_x = 0;
    t_info.offset_y = 0;
    /* Swap numerator and denominator as time_base in AVCodecContext gives the
     * time period between frames, but theora_info needs the framerate.  */
    t_info.fps_numerator = avc_context->time_base.den;
    t_info.fps_denominator = avc_context->time_base.num;
    if (avc_context->sample_aspect_ratio.num != 0) {
        t_info.aspect_numerator = avc_context->sample_aspect_ratio.num;
        t_info.aspect_denominator = avc_context->sample_aspect_ratio.den;
    } else {
        t_info.aspect_numerator = 1;
        t_info.aspect_denominator = 1;
    }
    t_info.colorspace = OC_CS_UNSPECIFIED;
    t_info.pixelformat = OC_PF_420;
    t_info.target_bitrate = avc_context->bit_rate;
    t_info.keyframe_frequency = avc_context->gop_size;
    t_info.keyframe_frequency_force = avc_context->gop_size;
    t_info.keyframe_mindistance = avc_context->keyint_min;
    t_info.quality = 0;

    t_info.quick_p = 1;
    t_info.dropframes_p = 0;
    t_info.keyframe_auto_p = 1;
    t_info.keyframe_data_target_bitrate = t_info.target_bitrate * 1.5;
    t_info.keyframe_auto_threshold = 80;
    t_info.noise_sensitivity = 1;
    t_info.sharpness = 0;

    /* Now initialise libtheora */
    if (theora_encode_init( &(h->t_state), &t_info ) != 0) {
        av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n");
        return -1;
    }

    /* Clear up theora_info struct */
    theora_info_clear( &t_info );

    /*
        Output first header packet consisting of theora
        header, comment, and tables.

        Each one is prefixed with a 16bit size, then they
        are concatenated together into ffmpeg's extradata.
    */
    offset = 0;

    /* Header */
    theora_encode_header( &(h->t_state), &o_packet );
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
        return -1;
    }

    /* Comment */
    theora_comment_init( &t_comment );
    theora_encode_comment( &t_comment, &o_packet );
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
        return -1;
    }

    /* Tables */
    theora_encode_tables( &(h->t_state), &o_packet );
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
        return -1;
    }

    /* Clear up theora_comment struct */
    theora_comment_clear( &t_comment );

    /* Set up the output AVFrame */
    avc_context->coded_frame= avcodec_alloc_frame();

    return 0;
}
Exemplo n.º 14
0
void DGVideo::load() {
    int stateFlag = 0;
    
    if (!_hasResource) {
        log->error(DGModVideo, "%s", DGMsg280005);
        return;
    }
    
    //log->trace(DGModVideo, "%s %s", DGMsg080001, _resource);
    
    _handle = fopen(_resource, "rb");
    
    if (_handle == NULL) {
        log->error(DGModVideo, "%s: %s", DGMsg280002, _resource);
        return;
    }
    
    ogg_sync_init(&_theoraInfo->oy);
    
    theora_comment_init(&_theoraInfo->tc);
    theora_info_init(&_theoraInfo->ti);
    
    while (!stateFlag) {
        size_t ret = _bufferData(&_theoraInfo->oy);
        
        if (ret == 0)
            break;
        
        while (ogg_sync_pageout(&_theoraInfo->oy, &_theoraInfo->og) > 0) {
            ogg_stream_state test;
            
            if (!ogg_page_bos(&_theoraInfo->og)) {
                _queuePage(_theoraInfo, &_theoraInfo->og);
                stateFlag = 1;
                break;
            }
            
            ogg_stream_init(&test, ogg_page_serialno(&_theoraInfo->og));
            ogg_stream_pagein(&test, &_theoraInfo->og);
            ogg_stream_packetout(&test, &_theoraInfo->op);
            
            if (!_theoraInfo->theora_p && 
                theora_decode_header(&_theoraInfo->ti, &_theoraInfo->tc, &_theoraInfo->op) >= 0) {
                memcpy(&_theoraInfo->to, &test, sizeof(test));
                _theoraInfo->theora_p = 1;
            } else {
                ogg_stream_clear(&test);
            }
        }
    }
    
    while (_theoraInfo->theora_p && _theoraInfo->theora_p < 3) {
        int ret;
        
        while (_theoraInfo->theora_p && (_theoraInfo->theora_p < 3) && 
               (ret = ogg_stream_packetout(&_theoraInfo->to, &_theoraInfo->op))) {
            if (ret < 0) {
                log->error(DGModVideo, "%s", DGMsg280003);
                return;
            }
            
            if (theora_decode_header(&_theoraInfo->ti, &_theoraInfo->tc, &_theoraInfo->op)) {
                log->error(DGModVideo, "%s", DGMsg280003);
                return;
            }
            
            _theoraInfo->theora_p++;
            if (_theoraInfo->theora_p == 3)
                break;
        }
        
        if (ogg_sync_pageout(& _theoraInfo->oy, & _theoraInfo->og) > 0)
            _queuePage(_theoraInfo, &_theoraInfo->og);
        else {
            size_t ret = _bufferData(&_theoraInfo->oy);
            if (ret == 0) {
                log->error(DGModVideo, "%s", DGMsg280004);
                return;
            }
        }
    }
    
    if (_theoraInfo->theora_p) {
        theora_decode_init(&_theoraInfo->td, &_theoraInfo->ti);
    } else {
        theora_info_clear(&_theoraInfo->ti);
        theora_comment_clear(&_theoraInfo->tc);
    }
    
    _currentFrame.width = _theoraInfo->ti.width;
    _currentFrame.height = _theoraInfo->ti.height;
    _currentFrame.depth = 24; // NOTE: We only support flat RGB for now
    _currentFrame.data = (unsigned char*)malloc((_theoraInfo->ti.width * _theoraInfo->ti.height) * 3);
    
    while (ogg_sync_pageout(&_theoraInfo->oy, &_theoraInfo->og) > 0) {
        _queuePage(_theoraInfo, &_theoraInfo->og);
    }
    
    _frameDuration = (float)(1/((double)_theoraInfo->ti.fps_numerator / _theoraInfo->ti.fps_denominator));
    _isLoaded = true;
}
Exemplo n.º 15
0
/* Opens the Ogg stream, searching for and initializing Theora and Vorbis media
 */
int alogg_open(APEG_LAYER *layer)
{
	ALOGG_INFO *info;
	int vok = 0, aok = 0;
	int flag, cs, size;

	info = calloc(1, sizeof(ALOGG_INFO));
	if(!info)
		return APEG_ERROR;
	LOCK_DATA(info, sizeof(ALOGG_INFO));

	ogg_sync_init(&info->osync);

	theora_comment_init(&info->tcomment);
	theora_info_init(&info->tinfo);

	vorbis_info_init(&info->vinfo);
	vorbis_comment_init(&info->vcomment);

	flag = FALSE;
	while(!flag)
	{
		int ret = buffer_data(layer, info);
		if(ret == 0)
			break;

		while(ogg_sync_pageout(&info->osync, &info->opage) > 0)
		{
			ogg_stream_state test;

			/* is this a mandated initial header? If not, stop parsing */
			if(!ogg_page_bos(&info->opage))
			{
				if(vok > 0)
					ogg_stream_pagein(&info->ostream[0], &info->opage);
				if(aok > 0)
					ogg_stream_pagein(&info->ostream[1], &info->opage);
				flag = TRUE;
				break;
			}

			ogg_stream_init(&test, ogg_page_serialno(&info->opage));
			ogg_stream_pagein(&test, &info->opage);
			ogg_stream_packetout(&test, &info->opkt);

			/* identify the codec: try theora */
			if(!vok && theora_decode_header(&info->tinfo, &info->tcomment,
			                                &info->opkt) >= 0)
			{
				/* it is theora */
				if(!_apeg_ignore_video)
				{
					memcpy(&info->ostream[0], &test, sizeof(test));
					vok = 1;
				}
				else
					ogg_stream_clear(&test);
			}
			else if(!aok && vorbis_synthesis_headerin(&info->vinfo,
			                                &info->vcomment, &info->opkt) >= 0)
			{
				/* it is vorbis */
				if(!_apeg_ignore_audio)
				{
					memcpy(&info->ostream[1], &test, sizeof(test));
					aok = 1;
				}
				else
					ogg_stream_clear(&test);
			}
			/* whatever it is, we don't care about it */
			else
				ogg_stream_clear(&test);
		}
		/* fall through to non-bos page parsing */
	}

	/* look for further theora headers */
	while((vok > 0 && vok < 3) || (aok > 0 && aok < 3))
	{
		int ret;
		// Get the last two of three Theora headers
		while(vok > 0 && vok < 3 &&
		      (ret = ogg_stream_packetout(&info->ostream[0], &info->opkt)))
		{
			if(ret < 0)
				goto error;

			if(theora_decode_header(&info->tinfo, &info->tcomment, &info->opkt))
				goto error;

			++vok;
		}

		// Get the last two of three Vorbis headers
		while(aok > 0 && aok < 3 &&
		      (ret = ogg_stream_packetout(&info->ostream[1], &info->opkt)))
		{
			if(ret < 0)
				goto error;

			if(vorbis_synthesis_headerin(&info->vinfo, &info->vcomment,
			                             &info->opkt))
				goto error;

			++aok;
		}

		if(ogg_sync_pageout(&info->osync, &info->opage) <= 0)
		{
			/* need more data */
			if(buffer_data(layer, info) == 0)
				break;
		}
		else
		{
			if(vok > 0)
				ogg_stream_pagein(&info->ostream[0], &info->opage);
			if(aok > 0)
				ogg_stream_pagein(&info->ostream[1], &info->opage);
		}
    }

	// Neither Vorbis or Theora fully initialized. Error.
	if(vok != 3 && aok != 3)
		goto error;

	layer->ogg_info = info;

	if(aok == 3)
	{
		vorbis_synthesis_init(&info->vdsp, &info->vinfo);
		vorbis_block_init(&info->vdsp, &info->vblock);

		if(info->vinfo.channels == 1)
			layer->stream.audio.down_channel = FALSE;

		layer->stream.audio.channels = info->vinfo.channels;
		layer->stream.audio.freq = info->vinfo.rate >>
		                           layer->stream.audio.down_sample;

		if(_apeg_audio_reset_parameters(layer) != APEG_OK)
		{
			vorbis_block_clear(&info->vblock);
			vorbis_dsp_clear(&info->vdsp);
			goto error;
		}

//		layer->audio.inited = TRUE;
		layer->stream.flags |= APEG_VORBIS_AUDIO;
	}
Exemplo n.º 16
0
int main(int argc,char *argv[]){

  ogg_packet op;

  int long_option_index;
  int c;

  FILE *infile = stdin;
  outfile = stdout;


#ifdef _WIN32 /* We need to set stdin/stdout to binary mode on windows. */
  /* Beware the evil ifdef. We avoid these where we can, but this one we
     cannot. Don't add any more, you'll probably go to hell if you do. */
  _setmode( _fileno( stdin ), _O_BINARY );
  _setmode( _fileno( stdout ), _O_BINARY );
#endif

  /* Process option arguments. */
  while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
    switch(c){
      case 'o':
      outfile=fopen(optarg,"wb");
      if(outfile==NULL){
        fprintf(stderr,"Unable to open output file '%s'\n", optarg);
        exit(1);
      }
      break;

      default:
        usage();
    }
  }
  if(optind<argc){
    infile=fopen(argv[optind],"rb");
    if(infile==NULL){
      fprintf(stderr,"Unable to open '%s' for extraction.\n", argv[optind]);
      exit(1);
    }
    if(++optind<argc){
      usage();
      exit(1);
    }
  }


  /*
     Ok, Ogg parsing. The idea here is we have a bitstream
     that is made up of Ogg pages. The libogg sync layer will
     find them for us. There may be pages from several logical
     streams interleaved; we find the first theora stream and
     ignore any others.

     Then we pass the pages for our stream to the libogg stream
     layer which assembles our original set of packets out of
     them. It's the packets that libtheora actually knows how
     to handle.
  */

  /* start up Ogg stream synchronization layer */
  ogg_sync_init(&oy);

  /* init supporting Theora structures needed in header parsing */
  theora_comment_init(&tc);
  theora_info_init(&ti);

  /* Ogg file open; parse the headers */

  /* Vorbis and Theora both depend on some initial header packets
     for decoder setup and initialization. We retrieve these first
     before entering the main decode loop. */

  /* Only interested in Theora streams */
  while(!stateflag){
    int ret=buffer_data(infile,&oy);
    if(ret==0)break;
    while(ogg_sync_pageout(&oy,&og)>0){
      ogg_stream_state test;

      /* is this a mandated initial header? If not, stop parsing */
      if(!ogg_page_bos(&og)){
        /* don't leak the page; get it into the appropriate stream */
        queue_page(&og);
        stateflag=1;
        break;
      }

      ogg_stream_init(&test,ogg_page_serialno(&og));
      ogg_stream_pagein(&test,&og);
      ogg_stream_packetout(&test,&op);

      /* identify the codec: try theora */
      if(!theora_p && theora_decode_header(&ti,&tc,&op)>=0){
        /* it is theora -- save this stream state */
        memcpy(&to,&test,sizeof(test));
        theora_p=1;
      }else{
        /* whatever it is, we don't care about it */
        ogg_stream_clear(&test);
      }
    }
    /* fall through to non-initial page parsing */
  }

  /* we're expecting more header packets. */
  while(theora_p && theora_p<3){
    int ret;

    /* look for further theora headers */
    while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
      if(ret<0){
        fprintf(stderr,"Error parsing Theora stream headers; corrupt stream?\n");
        exit(1);
      }
      if(theora_decode_header(&ti,&tc,&op)){
        printf("Error parsing Theora stream headers; corrupt stream?\n");
        exit(1);
      }
      theora_p++;
      if(theora_p==3)break;
    }


    /* The header pages/packets will arrive before anything else we
       care about, or the stream is not obeying spec */

    if(ogg_sync_pageout(&oy,&og)>0){
      queue_page(&og); /* demux into the stream state */
    }else{
      int ret=buffer_data(infile,&oy); /* need more data */
      if(ret==0){
        fprintf(stderr,"End of file while searching for codec headers.\n");
        exit(1);
      }
    }
  }

  /* Now we have all the required headers. initialize the decoder. */
  if(theora_p){
    theora_decode_init(&td,&ti);
    fprintf(stderr,"Ogg logical stream %x is Theora %dx%d %.02f fps video\nEncoded frame content is %dx%d with %dx%d offset\n",
            to.serialno,ti.width,ti.height, (double)ti.fps_numerator/ti.fps_denominator,
            ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
  }else{
    /* tear down the partial theora setup */
    theora_info_clear(&ti);
    theora_comment_clear(&tc);
  }

  /* open video */
  if(theora_p)open_video();

  /* install signal handler */
  signal (SIGINT, sigint_handler);

  /* Finally the main decode loop. 

     It's one Theora packet per frame, so this is pretty 
     straightforward if we're not trying to maintain sync
     with other multiplexed streams.

     the videobuf_ready flag is used to maintain the input
     buffer in the libogg stream state. If there's no output
     frame available at the end of the decode step, we must
     need more input data. We could simplify this by just 
     using the return code on ogg_page_packetout(), but the
     flag system extends easily to the case were you care
     about more than one multiplexed stream (like with audio
     playback). In that case, just maintain a flag for each
     decoder you care about, and pull data when any one of
     them stalls.

     videobuf_time holds the presentation time of the currently
     buffered video frame. We ignore this value.
  */

  stateflag=0; /* playback has not begun */
  /* queue any remaining pages from data we buffered but that did not
      contain headers */
  while(ogg_sync_pageout(&oy,&og)>0){
    queue_page(&og);
  }
  while(!got_sigint){

    while(theora_p && !videobuf_ready){
      /* theora is one in, one out... */
      if(ogg_stream_packetout(&to,&op)>0){

        theora_decode_packetin(&td,&op);
        videobuf_granulepos=td.granulepos;
        videobuf_time=theora_granule_time(&td,videobuf_granulepos);
        videobuf_ready=1;

      }else
        break;
    }

    if(!videobuf_ready && feof(infile))break;

    if(!videobuf_ready){
      /* no data yet for somebody.  Grab another page */
      int ret=buffer_data(infile,&oy);
      while(ogg_sync_pageout(&oy,&og)>0){
        queue_page(&og);
      }
    }
    /* dumpvideo frame, and get new one */
    else video_write();

    videobuf_ready=0;
  }

  /* end of decoder loop -- close everything */

  if(theora_p){
    ogg_stream_clear(&to);
    theora_clear(&td);
    theora_comment_clear(&tc);
    theora_info_clear(&ti);
  }
  ogg_sync_clear(&oy);

  if(infile && infile!=stdin)fclose(infile);

  fprintf(stderr,
          "\r                                                              "
          "\nDone.\n");
  return(0);

}
Exemplo n.º 17
0
bool TheoraEncodeInputPin::ConstructCodec() 
{
	//debugLog<<"Contructing codec..."<<endl;
	theora_info_init(&m_theoraInfo);
	
	//Round up to multiple of 16 for theora

	//---------------------------------------------------------------------------------------------------------------
	//m_theoraInfo values
	//==================
	//width, height					-	/16 up rounded values, size of the outer frame
	//frame_width, frame_height		-	size of the inner picture region
	//offset_x						-	Distance at bottom left from frame to picture  <= width - frame_width
	//offset_y						-	Distance at bottom left from frame to picture  <= height - frame_height

	//m_yuv values - for YV12 format
	//=============================
	//y_stride						-	Equal to the /16 up rounded wdith values
	//y_width						-	Equal to the /16 up rounded wdith values
	//uv_stride						-	Equal to *half* the /16 up rounded width values
	//uv_width						-	Equal to *half* the /16 up rounded wdith values
	//y_height						-	Equal to the /16 up rounded height value
	//uv_height						-	Equal to *half* the /16 up rounded height value
	//y								-	Buffer of size y_stride*y_height (/16 up rounded values)
	//u,v							-	Buffers each *quarter* the size of the y buffer (/16 up rounded values)

	//Member data
	//===========
	//m_width						-	raw video source values... equal to frame_width
	//m_height						-	raw video source values... equal to frame_height
	//m_xOffset						-	x offset
	//m_yOffset						-	y offset
	//---------------------------------------------------------------------------------------------------------------

	//Width of the outer frame
	m_theoraInfo.width			=	m_yuv.y_width
								=	m_yuv.y_stride
								=	(((m_width + 15)>>4)<<4);

	//Width of the inner picture
	m_theoraInfo.frame_width	=	m_width;
								

	//YUV U&V data
	m_yuv.uv_width				=	m_yuv.uv_stride
								=	m_yuv.y_width/2;

	
	//

	//Height data of outer frame
	m_theoraInfo.height			=	m_yuv.y_height
								=	(((m_height + 15)>>4)<<4);

	//Height of the inner picture
	m_theoraInfo.frame_height	=	m_height;

	m_yuv.uv_height				=	m_yuv.y_height/2;

	
	//

	//Set offset values... no longer centred... all the offset is at the bottom left of the image (ie very start of memory image)
	//Difference between the outframe dimensions and the inner picture dimensions
	m_theoraInfo.offset_x		=	m_xOffset
								=	(m_theoraInfo.width - m_theoraInfo.frame_width);

	m_theoraInfo.offset_y		=	m_yOffset
								=	(m_height - m_theoraInfo.frame_height);
	
	
	unsigned long locYBuffSize = m_yuv.y_height * m_yuv.y_stride;
	m_yuv.y				=	new unsigned char[locYBuffSize];
	m_yuv.u				=	new unsigned char[locYBuffSize/4];
	m_yuv.v				=	new unsigned char[locYBuffSize/4];

	//End YV12 specifics
	//

	//HACK:::Bit of a hack to convert dshow nanos to a fps num/denom.
	//Now we multiply the numerator and denom by 1000, this gives us 3 d.p. of precision for framerate.
	unsigned long locNum = (((double)10000000 * 1000) / ((double)m_averageTimePerFrame)) + (double)0.5;

	//debugLog<<"FPS = "<<locNum<<endl;
	m_theoraInfo.fps_numerator = locNum;
	m_theoraInfo.fps_denominator = 1000;
	
	m_theoraInfo.aspect_numerator=0;
	m_theoraInfo.aspect_denominator=0;
	
	m_theoraInfo.colorspace=OC_CS_UNSPECIFIED;		//YV12
	m_theoraInfo.target_bitrate=400000; //m_videoFormat->dwBitRate;

	//Hard code for now
	m_theoraInfo.quality=30; //video_q;

	m_theoraInfo.dropframes_p=0;
	m_theoraInfo.quick_p=1;
	m_theoraInfo.keyframe_auto_p=1;
	m_theoraInfo.keyframe_frequency=64;   //If you change this... change the logged value below
	m_theoraInfo.keyframe_frequency_force=64;  //ditto
	m_theoraInfo.keyframe_data_target_bitrate=m_theoraInfo.target_bitrate*1.5;
	m_theoraInfo.keyframe_auto_threshold=80;
	m_theoraInfo.keyframe_mindistance=8;
	m_theoraInfo.noise_sensitivity=1; 
    m_theoraInfo.pixelformat = OC_PF_420;

	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameRateNumerator = m_theoraInfo.fps_numerator;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameRateDenominator = m_theoraInfo.fps_denominator;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.maxKeyframeInterval = 6;   //log2(keyframe_freq) from above
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.pictureHeight = m_height;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.pictureWidth = m_width;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.colourSpace = OC_CS_UNSPECIFIED;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.outerFrameHeight = m_theoraInfo.height;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.outerFrameWidth = m_theoraInfo.width;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.xOffset = (unsigned char)m_xOffset;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.yOffset = (unsigned char)m_yOffset;
    ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.pixelFormat = m_theoraInfo.pixelformat; 

	//TODO ::: DO something about aspect ratios
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.aspectDenominator = 0;
	((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.aspectNumerator = 0;

	return true;

}
Exemplo n.º 18
0
static gboolean
theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
{
  GstStructure *structure = gst_caps_get_structure (caps, 0);
  GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
  const GValue *par;
  gint fps_n, fps_d;

  gst_structure_get_int (structure, "width", &enc->width);
  gst_structure_get_int (structure, "height", &enc->height);
  gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
  par = gst_structure_get_value (structure, "pixel-aspect-ratio");

  theora_info_clear (&enc->info);
  theora_info_init (&enc->info);
  /* Theora has a divisible-by-sixteen restriction for the encoded video size but
   * we can define a visible area using the frame_width/frame_height */
  enc->info_width = enc->info.width = (enc->width + 15) & ~15;
  enc->info_height = enc->info.height = (enc->height + 15) & ~15;
  enc->info.frame_width = enc->width;
  enc->info.frame_height = enc->height;

  /* center image if needed */
  if (enc->center) {
    /* make sure offset is even, for easier decoding */
    enc->offset_x = GST_ROUND_UP_2 ((enc->info_width - enc->width) / 2);
    enc->offset_y = GST_ROUND_UP_2 ((enc->info_height - enc->height) / 2);
  } else {
    enc->offset_x = 0;
    enc->offset_y = 0;
  }
  enc->info.offset_x = enc->offset_x;
  enc->info.offset_y = enc->offset_y;

  enc->info.fps_numerator = enc->fps_n = fps_n;
  enc->info.fps_denominator = enc->fps_d = fps_d;
  if (par) {
    enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
    enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
  } else {
    /* setting them to 0 indicates that the decoder can chose a good aspect
     * ratio, defaulting to 1/1 */
    enc->info.aspect_numerator = 0;
    enc->info.aspect_denominator = 0;
  }

  enc->info.colorspace = OC_CS_UNSPECIFIED;
  enc->info.target_bitrate = enc->video_bitrate;
  enc->info.quality = enc->video_quality;

  enc->info.dropframes_p = 0;
  enc->info.quick_p = (enc->quick ? 1 : 0);
  enc->info.keyframe_auto_p = (enc->keyframe_auto ? 1 : 0);
  enc->info.keyframe_frequency = enc->keyframe_freq;
  enc->info.keyframe_frequency_force = enc->keyframe_force;
  enc->info.keyframe_data_target_bitrate = enc->video_bitrate * 1.5;
  enc->info.keyframe_auto_threshold = enc->keyframe_threshold;
  enc->info.keyframe_mindistance = enc->keyframe_mindistance;
  enc->info.noise_sensitivity = enc->noise_sensitivity;
  enc->info.sharpness = enc->sharpness;

  /* as done in theora */
  enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
  GST_DEBUG_OBJECT (enc,
      "keyframe_frequency_force is %d, granule shift is %d",
      enc->info.keyframe_frequency_force, enc->granule_shift);

  theora_enc_reset (enc);
  enc->initialised = TRUE;

  gst_object_unref (enc);

  return TRUE;
}
Exemplo n.º 19
0
qboolean OGV_StartRead(cinematic_t *cin)
{
	int        status;
	ogg_page   og;
	ogg_packet op;
	int        i;

	cin->data = Com_Allocate(sizeof(cin_ogv_t));
	Com_Memset(cin->data, 0, sizeof(cin_ogv_t));

	ogg_sync_init(&g_ogm->oy);  /* Now we can read pages */

	//FIXME? can serialno be 0 in ogg? (better way to check inited?)
	//TODO: support for more than one audio stream? / detect files with one stream(or without correct ones)
	while (!g_ogm->os_audio.serialno || !g_ogm->os_video.serialno)
	{
		if (ogg_sync_pageout(&g_ogm->oy, &og) == 1)
		{
			if (strstr((char *)(og.body + 1), "vorbis"))
			{
				//FIXME? better way to find audio stream
				if (g_ogm->os_audio.serialno)
				{
					Com_Printf(S_COLOR_YELLOW "WARNING: more than one audio stream, in ogm-file(%s) ... we will stay at the first one\n", cin->name);
				}
				else
				{
					ogg_stream_init(&g_ogm->os_audio, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm->os_audio, &og);
				}
			}
			if (strstr((char *)(og.body + 1), "theora"))
			{
				if (g_ogm->os_video.serialno)
				{
					Com_Printf(S_COLOR_YELLOW "WARNING: more than one video stream, in ogm-file(%s) ... we will stay at the first one\n", cin->name);
				}
				else
				{
					ogg_stream_init(&g_ogm->os_video, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm->os_video, &og);
				}
			}
		}
		else if (OGV_LoadBlockToSync(cin))
		{
			break;
		}
	}

	if (!g_ogm->os_audio.serialno)
	{
		Com_Printf(S_COLOR_YELLOW "WARNING: Haven't found a audio(vorbis) stream in ogm-file (%s)\n", cin->name);
		return qfalse;
	}

	if (!g_ogm->os_video.serialno)
	{
		Com_Printf(S_COLOR_YELLOW "WARNING: Haven't found a video stream in ogm-file (%s)\n", cin->name);
		return qfalse;
	}

	//load vorbis header
	vorbis_info_init(&g_ogm->vi);
	vorbis_comment_init(&g_ogm->vc);
	i = 0;
	while (i < 3)
	{
		status = ogg_stream_packetout(&g_ogm->os_audio, &op);
		if (status < 0)
		{
			Com_Printf(S_COLOR_YELLOW "WARNING: Corrupt ogg packet while loading vorbis-headers, ogm-file(%s)\n", cin->name);
			return qfalse;
		}
		if (status > 0)
		{
			status = vorbis_synthesis_headerin(&g_ogm->vi, &g_ogm->vc, &op);
			if (i == 0 && status < 0)
			{
				Com_Printf(S_COLOR_YELLOW "WARNING: This Ogg bitstream does not contain Vorbis audio data, ogm-file(%s)\n", cin->name);
				return qfalse;
			}
			++i;
		}
		else if (OGV_LoadPagesToStreams(cin))
		{
			if (OGV_LoadBlockToSync(cin))
			{
				Com_Printf(S_COLOR_YELLOW "WARNING: Couldn't find all vorbis headers before end of ogm-file (%s)\n", cin->name);
				return qfalse;
			}
		}
	}

	vorbis_synthesis_init(&g_ogm->vd, &g_ogm->vi);

	// Do init
	{
		theora_info_init(&g_ogm->th_info);
		theora_comment_init(&g_ogm->th_comment);

		i = 0;
		while (i < 3)
		{
			status = ogg_stream_packetout(&g_ogm->os_video, &op);
			if (status < 0)
			{
				Com_Printf(S_COLOR_YELLOW "WARNING: Corrupt ogg packet while loading theora-headers, ogm-file(%s)\n", cin->name);
				return qfalse;
			}
			else if (status > 0)
			{
				status = theora_decode_header(&g_ogm->th_info, &g_ogm->th_comment, &op);
				if (i == 0 && status != 0)
				{
					Com_Printf(S_COLOR_YELLOW "WARNING: This Ogg bitstream does not contain theora data, ogm-file(%s)\n", cin->name);
					return qfalse;
				}
				++i;
			}
			else if (OGV_LoadPagesToStreams(cin))
			{
				if (OGV_LoadBlockToSync(cin))
				{
					Com_Printf(S_COLOR_YELLOW "WARNING: Couldn't find all theora headers before end of ogm-file (%s)\n", cin->name);
					return qfalse;
				}
			}
		}

		theora_decode_init(&g_ogm->th_state, &g_ogm->th_info);

		g_ogm->Vtime_unit = ((ogg_int64_t) g_ogm->th_info.fps_denominator * 1000 * 10000 / g_ogm->th_info.fps_numerator);
	}

	Com_DPrintf("Theora init done (%s)\n", cin->name);
	return qtrue;
}
Exemplo n.º 20
0
/*
 * init driver
 */
static int init(sh_video_t *sh){
    theora_struct_t *context = NULL;
    int failed = 1;
    int errorCode = 0;
    ogg_packet op;
    int i;

    /* check whether video output format is supported */
    switch(sh->codec->outfmt[sh->outfmtidx])
    {
       case IMGFMT_YV12: /* well, this should work... */ break;
       default: 
	  mp_msg (MSGT_DECVIDEO,MSGL_ERR,"Unsupported out_fmt: 0x%X\n",
		  sh->codec->outfmt[sh->outfmtidx]);
	  return 0;
    }

    /* this is not a loop, just a context, from which we can break on error */
    do
    {
       context = calloc (sizeof (theora_struct_t), 1);
       sh->context = context;
       if (!context)
	  break;

       theora_info_init(&context->inf);
       theora_comment_init(&context->cc);
       
       /* Read all header packets, pass them to theora_decode_header. */
       for (i = 0; i < THEORA_NUM_HEADER_PACKETS; i++)
       {
          op.bytes = ds_get_packet (sh->ds, &op.packet);
          op.b_o_s = 1;
          if ( (errorCode = theora_decode_header (&context->inf, &context->cc, &op)) )
          {
            mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Broken Theora header; errorCode=%i!\n", errorCode);
            break;
          }
       }
       if (errorCode)
          break;

       /* now init codec */
       errorCode = theora_decode_init (&context->st, &context->inf);
       if (errorCode)
       {
	  mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Theora decode init failed: %i \n",
		 errorCode);
	  break;
       }
       failed = 0;
    } while (0);

    if (failed)
    {
       if (context)
       {
	  free (context);
	  sh->context = NULL;
       }
       return 0;
    }

    if(sh->aspect==0.0 && context->inf.aspect_denominator!=0)
    {
       sh->aspect = (float)(context->inf.aspect_numerator * context->inf.frame_width)/
          (context->inf.aspect_denominator * context->inf.frame_height);
    }
    
    mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: Theora video init ok!\n");

    return mpcodecs_config_vo (sh,context->inf.frame_width,context->inf.frame_height,IMGFMT_YV12);
}
Exemplo n.º 21
0
gboolean ucil_theora_combine_av_file( const char *path, const char *codec, gboolean remove, ucil_processing_info_func_t procfunc, void *func_data, GError **error )
{
   FILE *f;
   FILE *af;
   FILE *vf;
   
   gchar *apath;
   gchar *vpath;

   long len;
   long filepos = 0;

   ogg_sync_state   oy;
   ogg_stream_state tins;
   theora_comment   tc;
   theora_info      ti;
   theora_state     ts;

   ogg_stream_state vs;
   vorbis_info      vi;
   vorbis_comment   vc;
   vorbis_dsp_state vd;
   vorbis_block     vb;
   
   ogg_page og;
   ogg_packet op;
   ogg_packet header_comm;
   ogg_packet header_code;
   

   int pkt;
   double videopos, audiopos;

   f = fopen( path, "w" );
   if( !f )
   {
      gchar *name = g_filename_display_name( path );
      g_set_error( error, G_FILE_ERROR, g_file_error_from_errno( errno ),
		   _("Could not open '%s' for writing: %s"),
                   name, g_strerror( errno ) );
      g_free( name );
      return FALSE;
   }
   
   apath = g_strconcat( path, ".atmp", NULL );

   af = fopen( apath, "r" );
   if( !af )
   {
      gchar *name = g_filename_display_name( apath );
      g_set_error( error, G_FILE_ERROR, g_file_error_from_errno( errno ),
		   _("Could not open '%s' for reading: %s"),
                   name, g_strerror( errno ) );
      g_free( name );
      g_free( apath );
      fclose( f );
      return FALSE;
   }
   
   vpath = g_strconcat( path, ".vtmp", NULL );
   
   vf = fopen( vpath, "r" );
   if( !vf )
   {
      gchar *name = g_filename_display_name( vpath );
      g_set_error( error, G_FILE_ERROR, g_file_error_from_errno( errno ),
		   _("Could not open '%s' for reading: %s"),
                   name, g_strerror( errno ) );
      g_free( name );
      g_free( apath );
      g_free( vpath );
      fclose( f );
      fclose( af );
      return FALSE;
   }
   
   fseek( af, 0L, SEEK_END );
   len = ftell( af );
   fseek( af, 0L, SEEK_SET );

   ogg_sync_init( &oy );
   theora_comment_init( &tc );
   theora_info_init( &ti );

   if( ogg_stream_init( &vs, 2 ) != 0 )
   {
      g_free( apath );
      g_free( vpath );
      fclose( f ); fclose( af ); fclose( vf );
      g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
		   _("Failed to initialize audio stream") );
      return FALSE;
   }
   vorbis_info_init( &vi );
   if( vorbis_encode_init( &vi, 2, 44100, -1, 128000, -1 ) )
   {
      g_free( apath );
      g_free( vpath );
      fclose( f ); fclose( af ); fclose( vf );
      g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
		   _("Failed to initialize audio encoder") );
      return FALSE;
   }
   vorbis_comment_init( &vc );
   vorbis_analysis_init( &vd, &vi );
   vorbis_block_init( &vd, &vb );

   //
   // write theora header page
   //
   {
      ogg_page og;
      
      while( ogg_sync_pageout( &oy, &og ) == 0 )
      {
	 int bytes;
	 
	 bytes = buffer_data( vf, &oy );
	 if( bytes == 0 )
	 {
	    g_free( apath );
	    g_free( vpath );
	    fclose( f ); fclose( af ); fclose( vf );
	    g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
			 _("Invalid video stream") );
	    return FALSE;
	 }
      }
      if( !ogg_page_bos( &og ) )
      {
	 g_free( apath );
	 g_free( vpath );
	 fclose( f ); fclose( af ); fclose( vf );
	 g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
		      _("Invalid video stream") );
	 return FALSE;
      }
      ogg_stream_init( &tins, ogg_page_serialno( &og ) );

      fwrite( og.header, 1, og.header_len, f );
      fwrite( og.body, 1, og.body_len, f );

      if( ogg_stream_pagein( &tins, &og ) < 0 )
      {
	 g_free( apath );
	 g_free( vpath );
	 fclose( f ); fclose( af ); fclose( vf );
	 g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
		      _("Invalid video stream") );
	 return FALSE;
      }
      pkt = 0;
      while( ( pkt < 3 ) && ( ogg_stream_packetout( &tins, &op ) > 0 ) )
      {
	 if( theora_decode_header( &ti, &tc, &op ) != 0 )
	 {
	    g_free( apath );
	    g_free( vpath );
	    fclose( f ); fclose( af ); fclose( vf );
	    g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
			 _("Invalid video stream") );
	    return FALSE;
	 }
	 pkt++;
      }
   }
   
   //
   // Write vorbis header page
   //
   vorbis_analysis_headerout( &vd, &vc, &op, &header_comm, &header_code );
   ogg_stream_packetin( &vs, &op );
   if( ogg_stream_pageout( &vs, &og ) != 1 )
   {
      g_free( apath );
      g_free( vpath );
      fclose( f ); fclose( af ); fclose( vf );
      g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
		   _("Could not create audio stream") );
      return FALSE;
   }
   fwrite( og.header, 1, og.header_len, f );
   fwrite( og.body,   1, og.body_len, f );
   
   ogg_stream_packetin( &vs, &header_comm );
   ogg_stream_packetin( &vs, &header_code );

   // write remaining theora headers
   for( pkt = 1; pkt < 3; )
   {
      ogg_page og;
      
      if( ogg_sync_pageout( &oy, &og ) > 0 )
      {
	 
	 fwrite( og.header, 1, og.header_len, f );
	 fwrite( og.body, 1, og.body_len, f );

	 if( ogg_stream_pagein( &tins, &og ) < 0 )
	 {
	    g_free( apath );
	    g_free( vpath );
	       fclose( f ); fclose( af ); fclose( vf );
	       g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
			    _("Invalid video stream") );
	       return FALSE;
	 }
	 
	 while( ( pkt < 3 ) && ( ogg_stream_packetout( &tins, &op ) > 0 ) )
	 {
	    if( theora_decode_header( &ti, &tc, &op ) != 0 )
	    {
	       g_free( apath );
	       g_free( vpath );
	       fclose( f ); fclose( af ); fclose( vf );
	       g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
			    _("Invalid video stream") );
	       return FALSE;
	    }
	    pkt++;
	 }
      }
      else
      {
	 int bytes;
	 
	 bytes = buffer_data( vf, &oy );
	 if( bytes == 0 )
	 {
	    g_free( apath );
	    g_free( vpath );
	    fclose( f ); fclose( af ); fclose( vf );
	    g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, 
			 _("Invalid video stream") );
	    return FALSE;
	 }
      }
   }

   theora_decode_init( &ts, &ti );
   

   //
   // Write remaining vorbis headers
   //
   while( ogg_stream_flush( &vs, &og ) > 0 )
   {
      fwrite( og.header, 1, og.header_len, f );
      fwrite( og.body,   1, og.body_len, f );
   }

   audiopos = 0.0;
   videopos = 0.0;
   
   while( !feof( af ) )
   {
      signed char abuf[512 * 4];
      int n_samples;
      
      if( feof( vf ) || ( audiopos <= videopos ) )
      {
	 n_samples = fread( abuf, 4, 512, af );
	 audiopos = encode_vorbis( f, &vd, &vs, &vb, 44100, audiopos, abuf, n_samples );
	 filepos += n_samples * 4;
      }
      else
      {
	 buffer_data( vf, &oy );
	 
	 if( ogg_sync_pageout( &oy, &og ) > 0 )
	 {
	    double tmppos;
	    fwrite( og.header, 1, og.header_len, f );
	    fwrite( og.body, 1, og.body_len, f );
	    if( ogg_stream_pagein( &tins, &og ) < 0 )
	    {
	       TRACE( "failed to decode theora\n" );
	    }
	    ogg_stream_packetout( &tins, &op );
	    tmppos = theora_granule_time( &ts, ogg_page_granulepos( &og ) );
	    if( tmppos > 0 )
	    {
	       videopos = tmppos;
	    }	    
	 }
      }

      if( procfunc )
      {
	 procfunc( func_data, (double)filepos/(double)len );
      }
   }

   while( !feof( vf ) && buffer_data( vf, &oy ) )
   {
      if( ogg_sync_pageout( &oy, &og ) > 0 )
      {
	 fwrite( og.header, 1, og.header_len, f );
	 fwrite( og.body, 1, og.body_len, f );
      }
   }

   if( remove )
   {
      unlink( vpath );
      unlink( apath );
   }

   g_free( vpath );
   g_free( apath );
   
   fclose( f );
   fclose( af );
   fclose( vf );
   
   return TRUE;
}
int main(int argc,char *argv[]){

  int i,j;
  ogg_packet op;

  FILE *infile = stdin;

#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
  /* Beware the evil ifdef. We avoid these where we can, but this one we
     cannot. Don't add any more, you'll probably go to hell if you do. */
  _setmode( _fileno( stdin ), _O_BINARY );
#endif

  /* open the input file if any */
  if(argc==2){
    infile=fopen(argv[1],"rb");
    if(infile==NULL){
      fprintf(stderr,"Unable to open '%s' for playback.\n", argv[1]);
      exit(1);
    }
  }
  if(argc>2){
      usage();
      exit(1);
  }

  /* start up Ogg stream synchronization layer */
  ogg_sync_init(&oy);

  /* init supporting Vorbis structures needed in header parsing */
  vorbis_info_init(&vi);
  vorbis_comment_init(&vc);

  /* init supporting Theora structures needed in header parsing */
  theora_comment_init(&tc);
  theora_info_init(&ti);

  /* Ogg file open; parse the headers */
  /* Only interested in Vorbis/Theora streams */
  while(!stateflag){
    int ret=buffer_data(infile,&oy);
    if(ret==0)break;
    while(ogg_sync_pageout(&oy,&og)>0){
      ogg_stream_state test;

      /* is this a mandated initial header? If not, stop parsing */
      if(!ogg_page_bos(&og)){
        /* don't leak the page; get it into the appropriate stream */
        queue_page(&og);
        stateflag=1;
        break;
      }

      ogg_stream_init(&test,ogg_page_serialno(&og));
      ogg_stream_pagein(&test,&og);
      ogg_stream_packetout(&test,&op);

      /* identify the codec: try theora */
      if(!theora_p && theora_decode_header(&ti,&tc,&op)>=0){
        /* it is theora */
        memcpy(&to,&test,sizeof(test));
        theora_p=1;
      }else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
        /* it is vorbis */
        memcpy(&vo,&test,sizeof(test));
        vorbis_p=1;
      }else{
        /* whatever it is, we don't care about it */
        ogg_stream_clear(&test);
      }
    }
    /* fall through to non-bos page parsing */
  }

  /* we're expecting more header packets. */
  while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){
    int ret;

    /* look for further theora headers */
    while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
      if(ret<0){
        fprintf(stderr,"Error parsing Theora stream headers; corrupt stream?\n");
        exit(1);
      }
      if(theora_decode_header(&ti,&tc,&op)){
        printf("Error parsing Theora stream headers; corrupt stream?\n");
        exit(1);
      }
      theora_p++;
      if(theora_p==3)break;
    }

    /* look for more vorbis header packets */
    while(vorbis_p && (vorbis_p<3) && (ret=ogg_stream_packetout(&vo,&op))){
      if(ret<0){
        fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n");
        exit(1);
      }
      if(vorbis_synthesis_headerin(&vi,&vc,&op)){
        fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n");
        exit(1);
      }
      vorbis_p++;
      if(vorbis_p==3)break;
    }

    /* The header pages/packets will arrive before anything else we
       care about, or the stream is not obeying spec */

    if(ogg_sync_pageout(&oy,&og)>0){
      queue_page(&og); /* demux into the appropriate stream */
    }else{
      int ret=buffer_data(infile,&oy); /* someone needs more data */
      if(ret==0){
        fprintf(stderr,"End of file while searching for codec headers.\n");
        exit(1);
      }
    }
  }

  /* and now we have it all.  initialize decoders */
  if(theora_p){
    theora_decode_init(&td,&ti);
    printf("Ogg logical stream %x is Theora %dx%d %.02f fps video\n",
           (unsigned int)to.serialno,ti.width,ti.height, 
           (double)ti.fps_numerator/ti.fps_denominator);
    if(ti.width!=ti.frame_width || ti.height!=ti.frame_height)
      printf("  Frame content is %dx%d with offset (%d,%d).\n",
           ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
    report_colorspace(&ti);
    dump_comments(&tc);
  }else{
    /* tear down the partial theora setup */
    theora_info_clear(&ti);
    theora_comment_clear(&tc);
  }
  if(vorbis_p){
    vorbis_synthesis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);
    fprintf(stderr,"Ogg logical stream %x is Vorbis %d channel %d Hz audio.\n",
            (unsigned int)vo.serialno,vi.channels,(int)vi.rate);
  }else{
    /* tear down the partial vorbis setup */
    vorbis_info_clear(&vi);
    vorbis_comment_clear(&vc);
  }

  /* open audio */
  if(vorbis_p)open_audio();

  /* open video */
  if(theora_p)open_video();

  /* install signal handler as SDL clobbered the default */
  signal (SIGINT, sigint_handler);

  /* on to the main decode loop.  We assume in this example that audio
     and video start roughly together, and don't begin playback until
     we have a start frame for both.  This is not necessarily a valid
     assumption in Ogg A/V streams! It will always be true of the
     example_encoder (and most streams) though. */

  stateflag=0; /* playback has not begun */
  while(!got_sigint){

    /* we want a video and audio frame ready to go at all times.  If
       we have to buffer incoming, buffer the compressed data (ie, let
       ogg do the buffering) */
    while(vorbis_p && !audiobuf_ready){
      int ret;
      float **pcm;

      /* if there's pending, decoded audio, grab it */
      if((ret=vorbis_synthesis_pcmout(&vd,&pcm))>0){
        int count=audiobuf_fill/2;
        int maxsamples=(audiofd_fragsize-audiobuf_fill)/2/vi.channels;
        for(i=0;i<ret && i<maxsamples;i++)
          for(j=0;j<vi.channels;j++){
            int val=rint(pcm[j][i]*32767.f);
            if(val>32767)val=32767;
            if(val<-32768)val=-32768;
            audiobuf[count++]=val;
          }
        vorbis_synthesis_read(&vd,i);
        audiobuf_fill+=i*vi.channels*2;
        if(audiobuf_fill==audiofd_fragsize)audiobuf_ready=1;
        if(vd.granulepos>=0)
          audiobuf_granulepos=vd.granulepos-ret+i;
        else
          audiobuf_granulepos+=i;
        
      }else{
        
        /* no pending audio; is there a pending packet to decode? */
        if(ogg_stream_packetout(&vo,&op)>0){
          if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
            vorbis_synthesis_blockin(&vd,&vb);
        }else   /* we need more data; break out to suck in another page */
          break;
      }
    }

    while(theora_p && !videobuf_ready){
      /* theora is one in, one out... */
      if(ogg_stream_packetout(&to,&op)>0){

        theora_decode_packetin(&td,&op);
        videobuf_granulepos=td.granulepos;
        
        videobuf_time=theora_granule_time(&td,videobuf_granulepos);

        /* is it already too old to be useful?  This is only actually
           useful cosmetically after a SIGSTOP.  Note that we have to
           decode the frame even if we don't show it (for now) due to
           keyframing.  Soon enough libtheora will be able to deal
           with non-keyframe seeks.  */

        if(videobuf_time>=get_time())
        videobuf_ready=1;
                
      }else
        break;
    }

    if(!videobuf_ready && !audiobuf_ready && feof(infile))break;

    if(!videobuf_ready || !audiobuf_ready){
      /* no data yet for somebody.  Grab another page */
      int bytes=buffer_data(infile,&oy);
      while(ogg_sync_pageout(&oy,&og)>0){
        queue_page(&og);
      }
    }

    /* If playback has begun, top audio buffer off immediately. */
    if(stateflag) audio_write_nonblocking();

    /* are we at or past time for this video frame? */
    if(stateflag && videobuf_ready && videobuf_time<=get_time()){
      video_write();
      videobuf_ready=0;
    }

    if(stateflag &&
       (audiobuf_ready || !vorbis_p) &&
       (videobuf_ready || !theora_p) &&
       !got_sigint){
      /* we have an audio frame ready (which means the audio buffer is
         full), it's not time to play video, so wait until one of the
         audio buffer is ready or it's near time to play video */
        
      /* set up select wait on the audiobuffer and a timeout for video */
      struct timeval timeout;
      fd_set writefs;
      fd_set empty;
      int n=0;

      FD_ZERO(&writefs);
      FD_ZERO(&empty);
      if(audiofd>=0){
        FD_SET(audiofd,&writefs);
        n=audiofd+1;
      }

      if(theora_p){
        long milliseconds=(videobuf_time-get_time())*1000-5;
        if(milliseconds>500)milliseconds=500;
        if(milliseconds>0){
          timeout.tv_sec=milliseconds/1000;
          timeout.tv_usec=(milliseconds%1000)*1000;

          n=select(n,&empty,&writefs,&empty,&timeout);
          if(n)audio_calibrate_timer(0);
        }
      }else{
        select(n,&empty,&writefs,&empty,NULL);
      }
    }

    /* if our buffers either don't exist or are ready to go,
       we can begin playback */
    if((!theora_p || videobuf_ready) &&
       (!vorbis_p || audiobuf_ready))stateflag=1;
    /* same if we've run out of input */
    if(feof(infile))stateflag=1;

  }

  /* tear it all down */

  audio_close();
  SDL_Quit();

  if(vorbis_p){
    ogg_stream_clear(&vo);
    vorbis_block_clear(&vb);
    vorbis_dsp_clear(&vd);
    vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi);
  }
  if(theora_p){
    ogg_stream_clear(&to);
    theora_clear(&td);
    theora_comment_clear(&tc);
    theora_info_clear(&ti);
  }
  ogg_sync_clear(&oy);

  if(infile && infile!=stdin)fclose(infile);

  fprintf(stderr,
          "\r                                                              "
          "\nDone.\n");
  return(0);

}
Exemplo n.º 23
0
static int
granulepos_test_encode (int frequency, int auto_p)
{
  theora_info ti;
  theora_state th;
  int result;
  int frame, tframe, keyframe, keydist;
  int shift;
  double rate, ttime;
  yuv_buffer yuv;
  unsigned char *framedata;
  ogg_packet op;
  long long int last_granule = -1;

/*  INFO ("+ Initializing theora_info struct"); */
  theora_info_init (&ti);

  ti.width = 32;
  ti.height = 32;
  ti.frame_width = ti.width;
  ti.frame_height = ti.frame_height;
  ti.offset_x = 0;
  ti.offset_y = 0;
  ti.fps_numerator = 16;
  ti.fps_denominator = 1;
  ti.aspect_numerator = 1;
  ti.aspect_denominator = 1;
  ti.colorspace = OC_CS_UNSPECIFIED;
  ti.pixelformat = OC_PF_420;
  ti.target_bitrate = 0;
  ti.quality = 16;

  ti.dropframes_p = 0;
  ti.quick_p = 1;

  /* check variations of automatic or forced keyframe choice */
  ti.keyframe_auto_p = auto_p;
  /* check with variations of the maximum gap */
  ti.keyframe_frequency = frequency;
  ti.keyframe_frequency_force = frequency;

  ti.keyframe_data_target_bitrate = ti.target_bitrate * 1.5;
  ti.keyframe_auto_threshold = 80;
  ti.keyframe_mindistance = MIN(8, frequency);
  ti.noise_sensitivity = 1;

/*  INFO ("+ Initializing theora_state for encoding"); */
  result = theora_encode_init (&th, &ti);
  if (result == OC_DISABLED) {
    INFO ("+ Clearing theora_state");
    theora_clear (&th);
  } else if (result < 0) {
    FAIL ("negative return code initializing encoder");
  }

/*  INFO ("+ Setting up dummy 4:2:0 frame data"); */
  framedata = calloc(ti.height, ti.width);
  yuv.y_width = ti.width;
  yuv.y_height = ti.height;
  yuv.y_stride = ti.width;
  yuv.y = framedata;
  yuv.uv_width = ti.width / 2;
  yuv.uv_height = ti.width / 2;
  yuv.uv_stride = ti.width;
  yuv.u = framedata;
  yuv.v = framedata;

  INFO ("+ Checking granulepos generation");
  shift = theora_granule_shift(&ti);
  rate = (double)ti.fps_denominator/ti.fps_numerator;
  for (frame = 0; frame < frequency * 2 + 1; frame++) {
    result = theora_encode_YUVin (&th, &yuv);
    if (result < 0) {
      printf("theora_encode_YUVin() returned %d\n", result);
      FAIL ("negative error code submitting frame for compression");
    }
    theora_encode_packetout (&th, frame >= frequency * 2, &op);
    if ((long long int)op.granulepos < last_granule)
      FAIL ("encoder returned a decreasing granulepos value");
    last_granule = op.granulepos;
    keyframe = op.granulepos >> shift;
    keydist = op.granulepos - (keyframe << shift);
    tframe = theora_granule_frame (&th, op.granulepos);
    ttime = theora_granule_time(&th, op.granulepos);
#if DEBUG
    printf("++ frame %d granulepos %lld %d:%d %d %.3lfs\n", 
	frame, (long long int)op.granulepos, keyframe, keydist,
	tframe, theora_granule_time (&th, op.granulepos));
#endif
    if ((keyframe + keydist) != frame + 1)
      FAIL ("encoder granulepos does not map to the correct frame number");
    if (tframe != frame)
      FAIL ("theora_granule_frame returned incorrect results");
    if (fabs(rate*(frame+1) - ttime) > 1.0e-6)
      FAIL ("theora_granule_time returned incorrect results");
  }

  /* clean up */
/*  INFO ("+ Freeing dummy frame data"); */
  free (framedata);

/*  INFO ("+ Clearing theora_info struct"); */
  theora_info_clear (&ti);

/*  INFO ("+ Clearing theora_state"); */
  theora_clear (&th);

  return 0;
}
Exemplo n.º 24
0
void rmdInitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready){
    
    int y0,
        y1,
        y2,
        fname_length;
    ogg_stream_state m_ogg_skel;
    ogg_page skel_og_pg;
    fisbone_packet skel_fbv,    //video fisbone packet
                   skel_fba ;   //audio fisbone packet

    (pdata)->enc_data=enc_data_t;

    fname_length=strlen(pdata->args.filename);
    if(!(fname_length>4 &&
       pdata->args.filename[fname_length-4] == '.' &&
       (pdata->args.filename[fname_length-3] == 'o' ||
        pdata->args.filename[fname_length-3] == 'O') &&
       (pdata->args.filename[fname_length-2] == 'g' ||
        pdata->args.filename[fname_length-2] == 'G') &&
       (pdata->args.filename[fname_length-1] == 'v' ||
        pdata->args.filename[fname_length-1] == 'V'))){
    
        char *new_name=malloc(fname_length+5);
        strcpy(new_name,pdata->args.filename);
        strcat(new_name,".ogv");
        
        free(pdata->args.filename);
        pdata->args.filename=new_name;


    }
        
    if (!pdata->args.overwrite) {
        rmdIncrementalNaming(&(pdata)->args.filename);
        fprintf(stderr, "Output file: %s\n", pdata->args.filename);
    }
        
    enc_data_t->fp=fopen((pdata)->args.filename,"w");
    if(enc_data_t->fp==NULL){
        fprintf(stderr,"Cannot open file %s for writting!\n",
                       (pdata)->args.filename);
        exit(13);
    }

    //each stream must have a unique 
    srand(time(NULL));
    y0=rand()+1;
    y1=rand()+1;
    y2=rand()+1;
    y2+=(y1==y2);
    y0=(((y0==y1)||(y0==y2))?(y1+y2):y0);

    //init ogg streams
    //skeleton first
    ogg_stream_init(&m_ogg_skel,y0);
    m_add_fishead_packet(&m_ogg_skel);
	if(ogg_stream_pageout(&m_ogg_skel,&skel_og_pg)!= 1){
        fprintf (stderr, "Internal Ogg library error.\n");
        exit (2);
    }
    fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp);
    fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp);
    


    ogg_stream_init(&enc_data_t->m_ogg_ts,y1);
    if(!pdata->args.nosound)
        ogg_stream_init(&enc_data_t->m_ogg_vs,y2);


    theora_info_init(&enc_data_t->m_th_inf);
    enc_data_t->m_th_inf.frame_width                  = pdata->brwin.rrect.width;
    enc_data_t->m_th_inf.frame_height                 = pdata->brwin.rrect.height;
    enc_data_t->m_th_inf.width                        = ((enc_data_t->m_th_inf.frame_width + 15) >> 4) << 4;
    enc_data_t->m_th_inf.height                       = ((enc_data_t->m_th_inf.frame_height + 15) >> 4) << 4;
    enc_data_t->m_th_inf.offset_x                     = 0;
    enc_data_t->m_th_inf.offset_y                     = 0;

    enc_data_t->m_th_inf.fps_numerator                = pdata->args.fps * 100.0;
    enc_data_t->m_th_inf.fps_denominator              = 100;
    enc_data_t->m_th_inf.aspect_numerator             = 1;
    enc_data_t->m_th_inf.aspect_denominator           = 1;

    enc_data_t->m_th_inf.colorspace                   = OC_CS_UNSPECIFIED;
    enc_data_t->m_th_inf.pixelformat                  = OC_PF_420;

    enc_data_t->m_th_inf.target_bitrate               = pdata->args.v_bitrate;
    enc_data_t->m_th_inf.quality                      = pdata->args.v_quality;
    enc_data_t->m_th_inf.dropframes_p                 = 0;
    enc_data_t->m_th_inf.quick_p                      = 1;
    enc_data_t->m_th_inf.keyframe_auto_p              = 1;
    enc_data_t->m_th_inf.keyframe_frequency           = 64;
    enc_data_t->m_th_inf.keyframe_frequency_force     = 64;
    enc_data_t->m_th_inf.keyframe_data_target_bitrate = enc_data_t->m_th_inf.quality * 1.5;
    enc_data_t->m_th_inf.keyframe_auto_threshold      = 80;
    enc_data_t->m_th_inf.keyframe_mindistance         = 8;
    enc_data_t->m_th_inf.noise_sensitivity            = 1;
    enc_data_t->m_th_inf.sharpness                    = 2;

    theora_encode_init(&enc_data_t->m_th_st,&enc_data_t->m_th_inf);


    if(!pdata->args.nosound){
        int ret;
        vorbis_info_init(&enc_data_t->m_vo_inf);
        ret = vorbis_encode_init_vbr(&enc_data_t->m_vo_inf,
                                     pdata->args.channels,
                                     pdata->args.frequency,
                                     (float)pdata->args.s_quality*0.1);
        if(ret){
            fprintf(stderr,"Error while setting up vorbis stream quality!\n");
            exit(2);
        }
        vorbis_comment_init(&enc_data_t->m_vo_cmmnt);
        vorbis_analysis_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_inf);
        vorbis_block_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_block);
    }


    theora_encode_header(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1);
    ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1);
    if(ogg_stream_pageout(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pg)!=1){
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(2);
    }
    fwrite(enc_data_t->m_ogg_pg.header,1,
           enc_data_t->m_ogg_pg.header_len,
           enc_data_t->fp);
    fwrite(enc_data_t->m_ogg_pg.body,1,
           enc_data_t->m_ogg_pg.body_len,
           enc_data_t->fp);

    theora_comment_init(&enc_data_t->m_th_cmmnt);
    theora_comment_add_tag(&enc_data_t->m_th_cmmnt,"recordMyDesktop",VERSION);
    theora_encode_comment(&enc_data_t->m_th_cmmnt,&enc_data_t->m_ogg_pckt1);
    ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1);
    theora_encode_tables(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1);
    ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1);


    if(!pdata->args.nosound){
        ogg_packet header;
        ogg_packet header_comm;
        ogg_packet header_code;

        vorbis_analysis_headerout(&enc_data_t->m_vo_dsp,
                                  &enc_data_t->m_vo_cmmnt,
                                  &header,&header_comm,
                                  &header_code);
        ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header);
        if(ogg_stream_pageout(&enc_data_t->m_ogg_vs,&enc_data_t->m_ogg_pg)!=1){
            fprintf(stderr,"Internal Ogg library error.\n");
            exit(2);
        }
        fwrite(enc_data_t->m_ogg_pg.header,1,
               enc_data_t->m_ogg_pg.header_len,
               enc_data_t->fp);
        fwrite(enc_data_t->m_ogg_pg.body,1,
               enc_data_t->m_ogg_pg.body_len,
               enc_data_t->fp);

        ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_comm);
        ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_code);
    }

    //fishbone packets go here
    memset(&skel_fbv,0,sizeof(skel_fbv));
    skel_fbv.serial_no=enc_data_t->m_ogg_ts.serialno;
    skel_fbv.nr_header_packet=3;
    skel_fbv.granule_rate_n=enc_data_t->m_th_inf.fps_numerator;
    skel_fbv.granule_rate_d=enc_data_t->m_th_inf.fps_denominator;
    skel_fbv.start_granule=0;
    skel_fbv.preroll=0;
    skel_fbv.granule_shift=theora_granule_shift(&enc_data_t->m_th_inf);
    add_message_header_field(&skel_fbv,
                             "Content-Type",
                             "video/theora");

    add_fisbone_to_stream(&m_ogg_skel,&skel_fbv);

    if(!pdata->args.nosound){

        memset(&skel_fba,0,sizeof(skel_fba));
        skel_fba.serial_no=enc_data_t->m_ogg_vs.serialno;
        skel_fba.nr_header_packet=3;
        skel_fba.granule_rate_n=pdata->args.frequency;
        skel_fba.granule_rate_d=(ogg_int64_t)1;
        skel_fba.start_granule=0;
        skel_fba.preroll=2;
        skel_fba.granule_shift=0;
        add_message_header_field(&skel_fba,
                                 "Content-Type",
                                 "audio/vorbis");

        add_fisbone_to_stream(&m_ogg_skel,&skel_fba);
    
    }

    while(1){
        int result = ogg_stream_flush(&m_ogg_skel, &skel_og_pg);
        if(result<0){
            fprintf (stderr, "Internal Ogg library error.\n");
            exit(2);
        }
        if(result==0)
            break;
        fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp);
        fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp);
	}



    while(1){
        int result = ogg_stream_flush(&enc_data_t->m_ogg_ts,
                                      &enc_data_t->m_ogg_pg);
        if(result<0){
            fprintf(stderr,"Internal Ogg library error.\n");
            exit(2);
        }
        if(result==0)break;
        fwrite(enc_data_t->m_ogg_pg.header,1,
               enc_data_t->m_ogg_pg.header_len,
               enc_data_t->fp);
        fwrite(enc_data_t->m_ogg_pg.body,1,
               enc_data_t->m_ogg_pg.body_len,
               enc_data_t->fp);
    }

    if(!pdata->args.nosound){
        while(1){
            int result=ogg_stream_flush(&enc_data_t->m_ogg_vs,
                                        &enc_data_t->m_ogg_pg);
            if(result<0){
                fprintf(stderr,"Internal Ogg library error.\n");
                exit(2);
            }
            if(result==0)break;
            fwrite(enc_data_t->m_ogg_pg.header,1,
                   enc_data_t->m_ogg_pg.header_len,
                   enc_data_t->fp);
            fwrite(enc_data_t->m_ogg_pg.body,1,
                   enc_data_t->m_ogg_pg.body_len,
                   enc_data_t->fp);
        }
    }
    
    //skeleton eos
    add_eos_packet_to_stream(&m_ogg_skel);
	if(ogg_stream_flush(&m_ogg_skel,&skel_og_pg)<0){
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(2);
    }
    fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp);
    fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp);


    //theora buffer allocation, if any
    if(!buffer_ready){
        enc_data_t->yuv.y=(unsigned char *)malloc(enc_data_t->m_th_inf.height*
                          enc_data_t->m_th_inf.width);
        enc_data_t->yuv.u=(unsigned char *)malloc(enc_data_t->m_th_inf.height*
                          enc_data_t->m_th_inf.width/4);
        enc_data_t->yuv.v=(unsigned char *)malloc(enc_data_t->m_th_inf.height*
                          enc_data_t->m_th_inf.width/4);
        enc_data_t->yuv.y_width=enc_data_t->m_th_inf.width;
        enc_data_t->yuv.y_height=enc_data_t->m_th_inf.height;
        enc_data_t->yuv.y_stride=enc_data_t->m_th_inf.width;

        enc_data_t->yuv.uv_width=enc_data_t->m_th_inf.width/2;
        enc_data_t->yuv.uv_height=enc_data_t->m_th_inf.height/2;
        enc_data_t->yuv.uv_stride=enc_data_t->m_th_inf.width/2;
        enc_data_t->x_offset=enc_data_t->m_th_inf.offset_x;
        enc_data_t->y_offset=enc_data_t->m_th_inf.offset_y;
    }
    theora_info_clear(&enc_data_t->m_th_inf);

}
Exemplo n.º 25
0
static int
init_theora(mm_file *mf, ogg_page *pg)
{
    int pkts = 0;
    int res = 0;
    int rval = 0;
    theora_info *th_info = NULL;
    theora_comment th_comm;
    ogg_packet pkt;
    ogg_stream_state stream;

    assert(mf);
    th_info = (theora_info *)xmalloc(sizeof(*mf->video_info));
    theora_info_init(th_info);
    theora_comment_init(&th_comm);
    ogg_stream_init(&stream, ogg_page_serialno(pg));

    if (ogg_page_packets(pg) != 1 || ogg_page_granulepos(pg) != 0) {
        goto end;
    }

    if (ogg_stream_pagein(&stream, pg))
        /* should not happen */
    {
        goto end;
    }

    /* Three first packets must go successfully through the loop. */
    for (pkts = 0; pkts < 3; ++pkts) {
        while ((res = ogg_stream_packetpeek(&stream, &pkt)) != 1) {
            if (res < 0
                || get_page(mf, pg) <= 0
                || ogg_stream_pagein(&stream, pg) < 0) {
                rval = -1;
                goto end;
            }
        }

        switch (theora_decode_header(th_info, &th_comm, &pkt)) {
        case 0:
            break;

        case OC_VERSION:
        case OC_NEWPACKET:
            INFO1("incompatible theora file");

            /* fall through */
        case OC_BADHEADER:
        default:
            goto end;
        }

        /* decode successful so grab packet */
        ogg_stream_packetout(&stream, &pkt);
    }

    mf->video_ctx = (theora_state *)xmalloc(sizeof(*mf->video_ctx));
    mf->video = (ogg_stream_state *)xmalloc(sizeof(*mf->video));
    memcpy(mf->video, &stream, sizeof(stream));
    theora_decode_init(mf->video_ctx, th_info);
    mf->video_info = th_info;
    rval = 1;
end:
    theora_comment_clear(&th_comm);

    if (rval <= 0) {
        ogg_stream_clear(&stream);
        theora_info_clear(th_info);
        free(th_info);
        mf->video_info = NULL;
    }

    return rval;
}
Exemplo n.º 26
0
void JVideoServer::Init()
{return;
    memset( &m_StreamState, 0, sizeof( m_StreamState    ) );
    memset( &m_SyncState,   0, sizeof( m_SyncState      ) );
    memset( &m_Page,        0, sizeof( m_Page           ) );
    memset( &m_Packet,      0, sizeof( m_Packet         ) );
    memset( &m_Comment,     0, sizeof( m_Comment        ) );
    memset( &m_Info,        0, sizeof( m_Info           ) );
    memset( &m_State,       0, sizeof( m_State          ) );
    memset( &m_YUVBuffer,   0, sizeof( m_YUVBuffer      ) );

    ogg_stream_clear( &m_StreamState );
    ogg_sync_init( &m_SyncState );
  
    theora_comment_init( &m_Comment );
    theora_info_init( &m_Info );

    // теперь ищем начало логического потока theora
    bool bStartHeader = true;
    int nHeaderPackets = 0;  // число обработанных пакетов заголовков theora

    do
    {
      if (LoadChunk( m_File, &m_SyncState ) ==0)
      {
        // кончился файл, на данном этапе это ошибка
        assert( "!eof searched, terminate...");
      }

      // ogg_sync_pageout - формирует страницу
      while (ogg_sync_pageout( &m_SyncState, &m_Page ) > 0)
        // 1-больше данных не требуется
        // 0-требуется больше данных для создания страницы
      {

        // что страница сформирована успешно

        // это страница заголовков? если нет, кончаем искать заголовки
        if (ogg_page_bos( &m_Page ) == false)
        {
          // нет, это не страница заголовков
          // значит, страницы заголовков всех логических потоков кончились
          // и начались данные этих потоков
          // таким образом надо переходить к чтению страниц данных

          // закидываем эту страничку в логический видеопоток
          PushPage( &m_Page );
          // PushPage - закидывает страничку
          // в логический поток theora, если
          // совпадает идентификатор логического потока
          // в противном случае страница игнорируется

          // выходим из циклов
          bStartHeader = false;
          break;
        }
        else
        {
          // да, это страница заголовков

          // тестовый логический поток
          ogg_stream_state m_StreamStateTest;
          memset(&m_StreamStateTest, 0x00, sizeof(ogg_stream_state));

          // инициализируем тестовый поток на тот же поток с таким же
          // идентификатором потока, как и у текущей странички
          if(0!= ogg_stream_init(&m_StreamStateTest,ogg_page_serialno(&m_Page)) )
            assert( "!error during ogg_stream_init");
          
          // добавляем страницу в тестовый поток
          if(0!= ogg_stream_pagein(&m_StreamStateTest,&m_Page) )
            assert( "!error during ogg_stream_pagein");

          // декодируем данные из этого тестового потока в пакет
          if( ogg_stream_packetout(&m_StreamStateTest,&m_Packet) ==-1)
            assert( "!error during ogg_stream_packetout");

          // nHeaderPackets - число прочитанных
          // заголовочных ПАКЕТОВ theora (не страниц)
          // по спецификации theora таких пакетов должно быть три
          if(nHeaderPackets==0)
          {
            int dhr = theora_decode_header (&m_Info, &m_Comment, &m_Packet);
            // декодируем заголовок theora

            if(dhr<0)
            {
              // это не заголовок theora
                
              // очищаем структуру тестового потока
              ogg_stream_clear(&m_StreamStateTest);
              //и продолжаем цикл в поисках заголовков theora
            }
            else
            {
              // это заголовок theora!

              // вот таким образом "инициализируем" логический поток theora:
              memcpy(&m_StreamState, &m_StreamStateTest,
                              sizeof(m_StreamStateTest));
              // теперь из этого потока будут всегда сыпаться пакеты theora

              nHeaderPackets++;

              // после того, как мы нашли заголовочную страницу логического потока theora,
              // нам необходимо прочитать все остальные заголовочные страницы
              // других потоков и отбросить их (если таковые, конечно, имеются)
            }
          }
        }
      }

    }
    while (bStartHeader);
 
    // сейчас надо получить еще два пакета заголовков theora (см. её документацию)
    // и можно переходить к потоковому воспроизведению

    while(nHeaderPackets<3)
    {
        int result=ogg_stream_packetout(&m_StreamState,&m_Packet);
        // если функция возвращает нуль, значит не хватает данных для декодирования
        // почему то этого НЕТ в спецификации libogg, или я плохо искал

        if (result < 0)
        {
          // ошибка декодирования, поврежденный поток
          assert( "!error during ogg_stream_packetout");
        }

        if (result > 0)
        {
          // удалось успешно извлечь пакет информации theora

          int result2 = theora_decode_header( &m_Info, &m_Comment, &m_Packet );

          if(result2<0)
          {
            // ошибка декодирования, поврежденный поток
            rlog.err("VIDEO: error during theora_decode_header (corrupt stream)");
          }

          ++nHeaderPackets;
        }

      // эту страничку обработали, надо извлечь новую
      // для этого проверяем буфер чтения, вдруг там осталось что-нить похожее
      // на страничку. Если не осталось, тогда просто читаем эти данные из файла:

      if (ogg_sync_pageout( &m_SyncState, &m_Page ) > 0)
        // ogg_sync_pageout - функция, берет данные из буфера приема ogg
        // и записывает их в ogg_page
      {
        //мы нашли страничку в буфере и...
        PushPage( &m_Page );
        // ...пихаем эти данные в подходящий поток
      }
      else
      {
        // ничего мы в буфере не нашли
        int ret = LoadChunk( m_File, &m_SyncState );
        // надо больше данных! читаем их из файла
        
        if (ret == 0)
        {
          // опять файл кончился!
          rlog.err("VIDEO: eof searched. terminate...");
        }
      }
    }

    // init videostream
    theora_decode_init( &m_State, &m_Info );

    switch(m_Info.colorspace)
    {
      case OC_CS_UNSPECIFIED:
        // nothing to report
        break;
      case OC_CS_ITU_REC_470M:
        rlog.msg("Encoder specified ITU Rec 470M (NTSC) color.");
        // выводим в лог информацию о цветовом пространстве
        break;
      case OC_CS_ITU_REC_470BG:
        rlog.msg("Encoder specified ITU Rec 470BG (PAL) color.");
        break;
      default:
        rlog.msg("Warning: encoder specified unknown colorspace.");
        break;
    }

  // theora processing...
  while (ogg_stream_packetout( &m_StreamState, &m_Packet ) <= 0)
  {
    // не хватает данных в логическом потоке theora
    // надо надергать данных из физического потока и затолкать их в логический поток

    // читаем данные из файла
    int ret = LoadChunk( m_File, &m_SyncState );
    if (ret == 0)
    {
      // файл кончился, необходимо выполнить закрывающие действия
      // и выйти из приложения
      TheoraClose();
      return;
    }

    while (ogg_sync_pageout( &m_SyncState, &m_Page ) > 0)
      // декодируем данные из буфера в страницы (ogg_page)
      // пока они не кончатся в буфере
    {
      // пихаем эти страницы в соотв. логические потоки
      PushPage( &m_Page );
    }
  }


   
  // удачно декодировали. в пакете содержится декодированная ogg-информация
  // (то бишь закодированная theora-информация)

  // загружаем пакет в декодер theora
  if (theora_decode_packetin(&m_State,&m_Packet) == OC_BADPACKET)
  {
    // ошибка декодирования
      rlog.err( "error during theora_decode_packetin..." );
  }

  // все данные получены, готовим кадр

  // декодируем страничку в YUV-виде в спец. структуру yuv_buffer
  if (theora_decode_YUVout( &m_State, &m_YUVBuffer ) != 0)
  {
    // ошибка декодирования
    rlog.err( "error during theora_decode_YUVout...");
  }
    
    // если это первый кадр, то создаем буфер кадра
    BYTE* frame = new BYTE[m_YUVBuffer.y_height*m_YUVBuffer.y_width*4];

  // yuv to rgb
  for (int cy = 0; cy < m_YUVBuffer.y_height; cy++)
  {
    int nYShift  = m_YUVBuffer.y_stride*cy;
    int nUVShift = m_YUVBuffer.uv_stride*(cy >> 1);
    
    for (int cx = 0; cx < m_YUVBuffer.y_width; cx++)
    {
      int nHX = (cx >> 1);

      BYTE nY = *(BYTE*)(m_YUVBuffer.y + nYShift  + cx  );
      BYTE nU = *(BYTE*)(m_YUVBuffer.u + nUVShift + nHX );
      BYTE nV = *(BYTE*)(m_YUVBuffer.v + nUVShift + nHX );

      int index = (cy*m_YUVBuffer.y_width + cx)*4;

      float r = nY + 1.371f*(nV - 128);
      float g = nY - 0.698f*(nV - 128) - 0.336f*(nU - 128);
      float b = nY + 1.732f*(nU - 128);

      frame[index + 0] = (BYTE)clamp( r, 0.0f, 255.0f );
      frame[index + 1] = (BYTE)clamp( g, 0.0f, 255.0f );
      frame[index + 2] = (BYTE)clamp( b, 0.0f, 255.0f );
      frame[index + 3] = 255;
    }
  }
} // JVideoServer::Init
Exemplo n.º 27
0
bool CTheoraPlayer::playVideo(
//Plays specified OGG Theora file to screen surface.
//If screen == NULL, then this method will test that the file is playable
//by decoding it as fast as possible but not displaying anything.
//
//Returns: whether playback was successful
	CStretchyBuffer& buffer, SDL_Surface *screen,
	const int x, const int y) //[default=(0,0)]
{
	//init
	theora_p = vorbis_p = 0;
	startticks = 0;
	bool bSkippedLastFrame = false;

	// start up Ogg stream synchronization layer
	ogg_sync_init(&oy);

	// init supporting Vorbis structures needed in header parsing
	vorbis_info_init(&vi);
	vorbis_comment_init(&vc);

	// init supporting Theora structures needed in header parsing
	theora_comment_init(&tc);
	theora_info_init(&ti);
	if (!screen)
		ti.quick_p = 1;
	ti.quality = 63;

	if (!parseHeaders(buffer))
		return false;

	// force audio off
	vorbis_p = 0;

	// initialize decoders
	if (theora_p) {
		theora_decode_init(&td,&ti);
#if 0
		printf("Ogg logical stream %x is Theora %dx%d %.02f fps video\n"
			  "  Frame content is %dx%d with offset (%d,%d).\n",
			to.serialno,ti.width,ti.height, (double)ti.fps_numerator/ti.fps_denominator,
			ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
		//report_colorspace(&ti); //we're not using this info for anything
		dump_comments(&tc);
#endif
	} else {
		// tear down the partial theora setup
		theora_info_clear(&ti);
		theora_comment_clear(&tc);
	}
	if(vorbis_p) {
		vorbis_synthesis_init(&vd,&vi);
		vorbis_block_init(&vd,&vb);  
		printf("Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
			vo.serialno,vi.channels,vi.rate);
	} else {
		// tear down the partial vorbis setup
		vorbis_info_clear(&vi);
		vorbis_comment_clear(&vc);
	}

	// open audio
	if (vorbis_p)
		open_audio();

	// open video
	SDL_Overlay *yuv_overlay = NULL;
	if (theora_p && screen)
		yuv_overlay = open_video(screen);
  
	// single frame video buffering
	ogg_packet op;
	ogg_int64_t  videobuf_granulepos=-1;
	double       videobuf_time=0;
	double last_frame_time = 0;
	bool hasdatatobuffer = true;

	// Main loop
	bool audiobuf_ready=false;
	bool videobuf_ready=false;
	bool playbackdone = (yuv_overlay == NULL);
	bool isPlaying = false;
	bool bBreakout = false;
	while (!playbackdone)
	{
		// break out on SDL quit event
		SDL_Event event;
		if (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
				case SDL_QUIT: playbackdone = bBreakout = true; break;
				case SDL_KEYDOWN:
					if (event.key.keysym.sym == SDLK_ESCAPE)
						playbackdone = bBreakout = true;
				break;
				default: break;
			}
		}

		while (theora_p && !videobuf_ready) {
			// get one video packet...
			if (ogg_stream_packetout(&to,&op)>0)
			{
				theora_decode_packetin(&td,&op);

				videobuf_granulepos=td.granulepos;
				videobuf_time=theora_granule_time(&td,videobuf_granulepos);

#if 0
				//Without sound channels to synch to, don't need to worry about skipping frames when slow.
				// update the frame counter
				//++frameNum;

				// check if this frame time has not passed yet.
				//	If the frame is late we need to decode additional
				//	ones and keep looping, since theora at this stage
				//	needs to decode all frames.
				const double now=get_time();
				const double delay=videobuf_time-now;
				if(delay>=0.0){
					/// got a good frame, not late, ready to break out
					videobuf_ready=true;
				} else if(now-last_frame_time>=1.0) {
					// display at least one frame per second, regardless
					videobuf_ready=true;
				} else {
					//Need to catch up -- no time to display frame.
					if (bSkippedLastFrame) //only allow skipping one frame in a row
						videobuf_ready = true; //show anyway
					else
						bSkippedLastFrame = true;
					//printf("dropping frame %d (%.3fs behind)\n", frameNum, -delay);
				}
#else
				videobuf_ready = true; //show every frame
#endif
			} else {
				// need more data
				break;
			}
		}

		if (!hasdatatobuffer && !videobuf_ready && !audiobuf_ready) {
			isPlaying = false;
			playbackdone = true;
		}

		//If we're set for the next frame, sleep.
		//In other words, don't show frames too rapidly. 
		if((!theora_p || videobuf_ready) && 
			(!vorbis_p || audiobuf_ready))
		{
			const int ticks = (int)(1000*(videobuf_time-get_time()));
			if(ticks>0 && screen) //don't need to sleep if only testing file
				SDL_Delay(ticks);
		}
 
		if (videobuf_ready)
		{
			// time to write our cached frame
			if (screen)
			{
				const bool bRes = video_write(screen, yuv_overlay, x, y);
				if (!bRes) //couldn't display image
					playbackdone = bBreakout = true;
			}
			videobuf_ready=false;
			last_frame_time=get_time();
			bSkippedLastFrame = false;

			// if audio has not started (first frame) then start it
			if ((!isPlaying)&&(vorbis_p)) {
				start_audio();
				isPlaying = true;
			}
		}

		// HACK: always look for more audio data
		audiobuf_ready=false;

		// buffer compressed data every loop
		if (hasdatatobuffer) {
			hasdatatobuffer = buffer_data(&oy, buffer) > 0;
			if (!hasdatatobuffer) {
				//printf("Ogg buffering stopped, end of file reached.\n");
			}
		}
    
		if (ogg_sync_pageout(&oy,&og)>0)
			queue_page(&og);

	} // playbackdone

	// show number of video frames decoded
	//printf("\nFrames decoded: %d\n", frameNum);

	// deinit
	if (vorbis_p) {
		audio_close();

		ogg_stream_clear(&vo);
		vorbis_block_clear(&vb);
		vorbis_dsp_clear(&vd);
		vorbis_comment_clear(&vc);
		vorbis_info_clear(&vi); 
	}
	if (theora_p) {
		if (yuv_overlay)
			SDL_FreeYUVOverlay(yuv_overlay);

		ogg_stream_clear(&to);
		theora_clear(&td);
		theora_comment_clear(&tc);
		theora_info_clear(&ti);
	}
	ogg_sync_clear(&oy);

	//If broken out of testing, return false since entire file was not verified.
	return !bBreakout || screen != NULL;
}
Exemplo n.º 28
0
static BGBBTJ_VidCodecCTX *theo_begin_compress(int fcc,
	BGBBTJ_BMPInfoHeader *in, BGBBTJ_BMPInfoHeader *out)
{
	byte tbuf[16384];
	ogg_packet op;
	BGBBTJ_VidCodecCTX *ctx;
	vfw_ctxinfo *info;
	byte *ct;
	int err, sz, xs, ys, xs1, ys1, px, py;

	if((fcc!=RIFF_TAG_THEO) && (fcc!=RIFF_TAG_theo) &&
			(fcc!=RIFF_TAG_ther))
		return(NULL);

	ctx=BGBBTJ_VidCodecCTX_New();
	info=gcalloc(sizeof(vfw_ctxinfo));
	ctx->data=info;

	info->ihead=gcalloc(sizeof(BGBBTJ_BMPInfoHeader));
	memset(info->ihead, 0, sizeof(BGBBTJ_BMPInfoHeader));
	info->ihead->biSize		= sizeof(BGBBTJ_BMPInfoHeader);
	info->ihead->biWidth		= in->biWidth;
	info->ihead->biHeight		= in->biHeight;
	info->ihead->biPlanes		= in->biPlanes;
	info->ihead->biBitCount		= in->biBitCount;
	info->ihead->biCompression	= in->biCompression;
	info->ihead->biSizeImage	=
		in->biWidth*in->biHeight*in->biBitCount/8;

//	out->biCompression=RIFF_TAG_ther;
	out->biCompression=RIFF_TAG_theo;

	info->ohead=gcalloc(sizeof(BGBBTJ_BMPInfoHeader));
	memset(info->ohead, 0, sizeof(BGBBTJ_BMPInfoHeader));
	info->ohead->biSize		= sizeof(BGBBTJ_BMPInfoHeader);
	info->ohead->biWidth		= out->biWidth;
//	info->ohead->biHeight		= -out->biHeight;
	info->ohead->biHeight		= out->biHeight;
	info->ohead->biPlanes		= out->biPlanes;
	info->ohead->biBitCount		= out->biBitCount;
	info->ohead->biCompression	= out->biCompression;
	info->ihead->biSizeImage	=
		out->biWidth*out->biHeight*out->biBitCount/8;

//	info->buffer=malloc(out->width*out->height*out->bpp/8);

	theora_info_init(&(info->ti));
//	if(err<0)printf("theo_begin_compress: A Err=%d\n");

	xs=(out->biWidth+15)&(~15);
	ys=(out->biHeight+15)&(~15);
	xs1=xs>>1;
	ys1=ys>>1;

    px=((xs-out->biWidth)>>1)&(~1);
    py=((ys-out->biHeight)>>1)&(~1);

	info->ti.width = out->biWidth;
	info->ti.height = out->biHeight;
	info->ti.frame_width = xs;
	info->ti.frame_height = ys;
    info->ti.offset_x=px;
	info->ti.offset_y=py;
//	info->ti.pixel_fmt=TH_PF_420;
	info->ti.pixelformat=TH_PF_420;
//	info->ti.quality=56;
	info->ti.quality=63;
	info->ti.colorspace=TH_CS_UNSPECIFIED;

	info->ti.fps_numerator=24;
	info->ti.fps_denominator=1;
	info->ti.aspect_numerator=1;
	info->ti.aspect_denominator=1;

	th_info_init(&(info->thi));
//	if(err<0)printf("theo_begin_compress: B Err=%d\n");

	info->thi.pic_width = out->biWidth;
	info->thi.pic_height = out->biHeight;
	info->thi.frame_width = xs;
	info->thi.frame_height = ys;
    info->thi.pic_x=px;
	info->thi.pic_y=py;
	info->thi.fps_numerator=24;
	info->thi.fps_denominator=1;

	info->thi.aspect_numerator=1;
	info->thi.aspect_denominator=1;
	
	info->thi.colorspace=TH_CS_UNSPECIFIED;
	info->thi.pixel_fmt=TH_PF_420;
//	info->thi.pixelformat=TH_PF_420;
//	info->thi.quality=48;
	info->thi.quality=63;

	if(theora_encode_init(&(info->th), &(info->ti)) != OC_DISABLED)
		{ theora_clear(&(info->th)); }

	info->td=th_encode_alloc(&(info->thi));
	th_info_clear(&(info->thi));
//	if(err<0)printf("theo_begin_compress: C Err=%d\n");

	th_comment_init(&(info->tc));
//	if(err<0)printf("theo_begin_compress: D Err=%d\n");

	ct=tbuf;
	
    err=th_encode_flushheader(info->td, &(info->tc), &op);
	if(err<0)printf("theo_begin_compress: E Err=%d\n");

	ct[0]=(op.bytes>>8)&255;
	ct[1]=op.bytes&255;
	ct+=2;

    memcpy(ct, op.packet, op.bytes);
    ct+=op.bytes;

    while(1)
    {
		err=th_encode_flushheader(info->td, &(info->tc), &op);
		if(err<=0)break;

		ct[0]=(op.bytes>>8)&255;
		ct[1]=op.bytes&255;
		ct+=2;

		memcpy(ct, op.packet, op.bytes);
		ct+=op.bytes;
    }

	if(err<0)printf("theo_begin_compress: F Err=%d\n");

	sz=ct-tbuf;
	ctx->vidStrd=gcalloc(sz);
	ctx->sz_vidStrd=sz;
	memcpy(ctx->vidStrd, tbuf, sz);

	info->ycbbuf[0].width=xs;
	info->ycbbuf[0].height=ys;
	info->ycbbuf[0].stride=xs;
	info->ycbbuf[0].data=malloc(xs*ys);

	info->ycbbuf[1].width=xs1;
	info->ycbbuf[1].height=ys1;
	info->ycbbuf[1].stride=xs1;
	info->ycbbuf[1].data=malloc(xs1*ys1);

	info->ycbbuf[2].width=xs1;
	info->ycbbuf[2].height=ys1;
	info->ycbbuf[2].stride=xs1;
	info->ycbbuf[2].data=malloc(xs1*ys1);

	ctx->compress_frame=&theo_compress_frame;

	return(ctx);
}
Exemplo n.º 29
0
int OggInit(CFile *f, OggData *data)
{
	ogg_packet packet;
	int num_vorbis;
#ifdef USE_THEORA
	int num_theora;
#endif
	int stream_start;
	int ret;

	unsigned magic;
	f->read(&magic, sizeof(magic));
	if (SDL_SwapLE32(magic) != 0x5367674F) { // "OggS" in ASCII
		return -1;
	}
	f->seek(0, SEEK_SET);

	ogg_sync_init(&data->sync);

	vorbis_info_init(&data->vinfo);
	vorbis_comment_init(&data->vcomment);

#ifdef USE_THEORA
	theora_info_init(&data->tinfo);
	theora_comment_init(&data->tcomment);
#endif

#ifdef USE_THEORA
	num_theora = 0;
#endif
	num_vorbis = 0;
	stream_start = 0;
	while (!stream_start) {
		ogg_stream_state test;

		if (OggGetNextPage(&data->page, &data->sync, f)) {
			return -1;
		}

		if (!ogg_page_bos(&data->page)) {
			if (num_vorbis) {
				ogg_stream_pagein(&data->astream, &data->page);
			}
#ifdef USE_THEORA
			if (num_theora) {
				ogg_stream_pagein(&data->vstream, &data->page);
			}
#endif
			stream_start = 1;
			break;
		}

		ogg_stream_init(&test, ogg_page_serialno(&data->page));
		ogg_stream_pagein(&test, &data->page);

		// initial codec headers
		while (ogg_stream_packetout(&test, &packet) == 1) {
#ifdef USE_THEORA
			if (theora_decode_header(&data->tinfo, &data->tcomment, &packet) >= 0) {
				memcpy(&data->vstream, &test, sizeof(test));
				++num_theora;
			} else
#endif
			if (!vorbis_synthesis_headerin(&data->vinfo, &data->vcomment, &packet)) {
				memcpy(&data->astream, &test, sizeof(test));
				++num_vorbis;
			} else {
				ogg_stream_clear(&test);
			}
		}
	}

	data->audio = num_vorbis;
#ifdef USE_THEORA
	data->video = num_theora;
#endif

	// remainint codec headers
	while ((num_vorbis && num_vorbis < 3)
#ifdef USE_THEORA
	  || (num_theora && num_theora < 3) ) {
		// are we in the theora page ?
		while (num_theora && num_theora < 3 &&
		  (ret = ogg_stream_packetout(&data->vstream, &packet))) {
			if (ret < 0) {
				return -1;
			}
			if (theora_decode_header(&data->tinfo, &data->tcomment, &packet)) {
				return -1;
			}
			++num_theora;
		}
#else
	  ) {
#endif

		// are we in the vorbis page ?
		while (num_vorbis && num_vorbis < 3 && 
		  (ret = ogg_stream_packetout(&data->astream, &packet))) {
			if (ret < 0) {
				return -1;
			}
			if (vorbis_synthesis_headerin(&data->vinfo, &data->vcomment, &packet)) {
				return -1;
				
			}
			++num_vorbis;
		}

		if (OggGetNextPage(&data->page, &data->sync, f)) {
				break;
		}

		if (num_vorbis) {
			ogg_stream_pagein(&data->astream, &data->page);
		}
#ifdef USE_THEORA
		if (num_theora) {
			ogg_stream_pagein(&data->vstream, &data->page);
		}
#endif
	}

	if (num_vorbis) {
		vorbis_synthesis_init(&data->vdsp, &data->vinfo);
		vorbis_block_init(&data->vdsp, &data->vblock);
	} else {
    	vorbis_info_clear(&data->vinfo);
    	vorbis_comment_clear(&data->vcomment);
	}

#ifdef USE_THEORA
	if (num_theora) {
		theora_decode_init(&data->tstate, &data->tinfo);
		data->tstate.internal_encode = NULL;  // needed for a bug in libtheora (fixed in next release)
	} else {
    	theora_info_clear(&data->tinfo);
    	theora_comment_clear(&data->tcomment);
	}

	return !(num_vorbis || num_theora);
#else
	return !num_vorbis;
#endif
}
Exemplo n.º 30
0
//TODO: vorbis/theora-header&init in sub-functions
//TODO: "clean" error-returns ...
int Cin_OGM_Init(const char* filename) {
	int status;
	ogg_page	og;
	ogg_packet	op;
	int i;

	if(g_ogm.ogmFile) {
		Com_Printf("WARNING: it seams there was already a ogm running, it will be killed to start %s\n", filename);
		Cin_OGM_Shutdown();
	}

	memset(&g_ogm,0,sizeof(cin_ogm_t));

	FS_FOpenFileRead(filename, &g_ogm.ogmFile, qtrue);
	if(!g_ogm.ogmFile) {
		Com_Printf("Can't open ogm-file for reading (%s)\n", filename);

		return -1;
	}

	ogg_sync_init(&g_ogm.oy); /* Now we can read pages */

	//FIXME? can serialno be 0 in ogg? (better way to check inited?)
	//TODO: support for more than one audio stream? / detect files with one stream(or without correct ones)
	while(!g_ogm.os_audio.serialno || !g_ogm.os_video.serialno) {
		if(ogg_sync_pageout(&g_ogm.oy,&og)==1) {
			if(strstr((char*)(og.body+1),"vorbis")) { //FIXME? better way to find audio stream
				if(g_ogm.os_audio.serialno) {
					Com_Printf("more than one audio stream, in ogm-file(%s) ... we will stay at the first one\n",filename);
				}
				else {
					ogg_stream_init(&g_ogm.os_audio, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm.os_audio,&og);
				}
			}
#ifdef USE_CIN_THEORA
			if(strstr((char*)(og.body+1),"theora")) {
				if(g_ogm.os_video.serialno) {
					Com_Printf("more than one video stream, in ogm-file(%s) ... we will stay at the first one\n",filename);
				}
				else{
					g_ogm.videoStreamIsTheora = qtrue;
					ogg_stream_init(&g_ogm.os_video, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm.os_video,&og);
				}
			}
#endif
#ifdef USE_CIN_XVID
			if(strstr((char*)(og.body+1),"video")) { //FIXME? better way to find video stream
				if(g_ogm.os_video.serialno) {
					Com_Printf("more than one video stream, in ogm-file(%s) ... we will stay at the first one\n",filename);
				}
				else{
					stream_header_t* sh;

					g_ogm.videoStreamIsXvid = qtrue;

					sh = (stream_header_t*)(og.body+1);
					//TODO: one solution for checking xvid and theora
					if(!isPowerOf2(sh->sh.stream_header_video.width)) {
						Com_Printf("VideoWidth of the ogm-file isn't a power of 2 value (%s)\n", filename);

						return -5;
					}
					if(!isPowerOf2(sh->sh.stream_header_video.height)) {
						Com_Printf("VideoHeight of the ogm-file isn't a power of 2 value (%s)\n", filename);

						return -6;
					}

					g_ogm.Vtime_unit = sh->time_unit;

					ogg_stream_init(&g_ogm.os_video, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm.os_video,&og);
				}
			}
#endif
		}
		else if(loadBlockToSync())
			break;
	}

	if(g_ogm.videoStreamIsXvid && g_ogm.videoStreamIsTheora) {
		Com_Printf("Found \"video\"- and \"theora\"-stream ,ogm-file (%s)\n", filename);

		return -2;
	}

	if(!g_ogm.os_audio.serialno) {
		Com_Printf("Haven't found a audio(vorbis) stream in ogm-file (%s)\n", filename);

		return -2;
	}
	if(!g_ogm.os_video.serialno) {
		Com_Printf("Haven't found a video stream in ogm-file (%s)\n", filename);

		return -3;
	}

	//load vorbis header
	vorbis_info_init(&g_ogm.vi);
	vorbis_comment_init(&g_ogm.vc);
	i=0;
	while(i<3) {
		status = ogg_stream_packetout(&g_ogm.os_audio,&op);
		if(status<0) {
			Com_Printf("Corrupt ogg packet while loading vorbis-headers, ogm-file(%s)\n", filename);

			return -8;
		}
		if(status>0) {
			status = vorbis_synthesis_headerin(&g_ogm.vi,&g_ogm.vc,&op);
			if(i==0 && status<0) {
				Com_Printf("This Ogg bitstream does not contain Vorbis audio data, ogm-file(%s)\n", filename);

				return -9;
			}
			++i;
		}
		else if(loadPagesToStreams()) {
			if(loadBlockToSync()) {
				Com_Printf("Couldn't find all vorbis headers before end of ogm-file (%s)\n", filename);

				return -10;
			}
		}
	}

	vorbis_synthesis_init(&g_ogm.vd,&g_ogm.vi);

#ifdef USE_CIN_XVID
	status = init_xvid();
	if (status) {
		Com_Printf("[Xvid]Decore INIT problem, return value %d(ogm-file: %s)\n", status, filename);

		return -4;
	}
#endif

#ifdef USE_CIN_THEORA
	if(g_ogm.videoStreamIsTheora) {
		ROQ_GenYUVTables();

		theora_info_init(&g_ogm.th_info);
		theora_comment_init(&g_ogm.th_comment);

		i=0;
		while(i<3) {
			status = ogg_stream_packetout(&g_ogm.os_video,&op);
			if(status<0) {
				Com_Printf("Corrupt ogg packet while loading theora-headers, ogm-file(%s)\n", filename);

				return -8;
			}
			if(status>0) {
				status = theora_decode_header(&g_ogm.th_info, &g_ogm.th_comment, &op);
				if(i==0 && status!=0) {
					Com_Printf("This Ogg bitstream does not contain theora data, ogm-file(%s)\n", filename);

					return -9;
				}
				++i;
			}
			else if(loadPagesToStreams()) {
				if(loadBlockToSync()) {
					Com_Printf("Couldn't find all theora headers before end of ogm-file (%s)\n", filename);

					return -10;
				}
			}
		}

		theora_decode_init(&g_ogm.th_state, &g_ogm.th_info);

		if(!isPowerOf2(g_ogm.th_info.width)) {
			Com_Printf("VideoWidth of the ogm-file isn't a power of 2 value (%s)\n", filename);

			return -5;
		}
		if(!isPowerOf2(g_ogm.th_info.height)) {
			Com_Printf("VideoHeight of the ogm-file isn't a power of 2 value (%s)\n", filename);

			return -6;
		}


		g_ogm.Vtime_unit = ((ogg_int64_t)g_ogm.th_info.fps_denominator *1000*10000 / g_ogm.th_info.fps_numerator);
	}
#endif

	Com_DPrintf("OGM-Init done (%s)\n",filename);

	return 0;
}