Example #1
0
static int
noop_test_encode ()
{
  th_info ti;
  th_enc_ctx *te;

  INFO ("+ Initializing th_info struct");
  th_info_init (&ti);

  INFO ("+ Testing encoder context with empty th_info");
  te = th_encode_alloc(&ti);
  if (te != NULL)
    FAIL("td_encode_alloc accepted an unconfigured th_info");

  INFO ("+ Setting 16x16 image size");
  ti.frame_width = 16;
  ti.frame_height = 16;

  INFO ("+ Allocating encoder context");
  te = th_encode_alloc(&ti);
  if (te == NULL)
    FAIL("td_encode_alloc returned a null pointer");

  INFO ("+ Clearing th_info struct");
  th_info_clear (&ti);

  INFO ("+ Freeing encoder context");
  th_encode_free(te);

  return 0;
}
Example #2
0
bool TheoraDecoder::initCodec() 
{
	th_comment_init(&mTheoraComment);
	th_info_init(&mTheoraInfo);
	
	return true;
 }
Example #3
0
File: theora.c Project: repstd/vlc
/*****************************************************************************
 * 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;
    p_sys->tcx = NULL;

    /* 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 */
    th_comment_init( &p_sys->tc );
    th_info_init( &p_sys->ti );

    return VLC_SUCCESS;
}
TheoraVideoStream::TheoraVideoStream(love::filesystem::File *file)
	: demuxer(file)
	, headerParsed(false)
	, decoder(nullptr)
	, frameReady(false)
	, lastFrame(0)
	, nextFrame(0)
{
	if (demuxer.findStream() != OggDemuxer::TYPE_THEORA)
		throw love::Exception("Invalid video file, video is not theora");

	th_info_init(&videoInfo);

	frontBuffer = new Frame();
	backBuffer = new Frame();

	try
	{
		parseHeader();
	}
	catch (love::Exception &ex)
	{
		delete backBuffer;
		delete frontBuffer;
		th_info_clear(&videoInfo);
		throw ex;
	}

	frameSync.set(new DeltaSync(), Acquire::NORETAIN);
}
Example #5
0
static void * create_theora()
  {
  theora_t * ret;
  ret = calloc(1, sizeof(*ret));
  th_info_init(&ret->ti);
  
  return ret;
  }
Example #6
0
IoTheoraInfo *IoTheoraInfo_rawClone(IoTheoraInfo *proto)
{
	IoObject *self = IoObject_rawClonePrimitive(proto);
	th_info* data = calloc(1, sizeof(th_info));
        th_info_init(data);
	IoObject_setDataPointer_(self, data);
	return self;
}
Example #7
0
/*
 * Theora beginning of stream
 */
nsresult
MediaRecorder::SetupTheoraBOS()
{
    int i;
    nsresult rv;
    PRUint32 wr;
    ogg_uint32_t keyframe;

    if (ogg_stream_init(&vState->os, rand())) {
        PR_LOG(log, PR_LOG_NOTICE, ("Failed ogg_stream_init\n"));
        return NS_ERROR_FAILURE;
    }

    th_info_init(&vState->ti);

    /* Must be multiples of 16 */
    vState->ti.frame_width = (params->width + 15) & ~0xF;
    vState->ti.frame_height = (params->height + 15) & ~0xF;
    vState->ti.pic_width = params->width;
    vState->ti.pic_height = params->height;
    vState->ti.pic_x = (vState->ti.frame_width - params->width) >> 1 & ~1;
    vState->ti.pic_y = (vState->ti.frame_height - params->height) >> 1 & ~1;
    vState->ti.fps_numerator = params->fps_n;
    vState->ti.fps_denominator = params->fps_d;

    /* Are these the right values? */
    keyframe = 64 - 1;
    for (i = 0; keyframe; i++)
        keyframe >>= 1;
    vState->ti.quality = (int)(params->qual * 100);
    vState->ti.colorspace = TH_CS_ITU_REC_470M;
    vState->ti.pixel_fmt = TH_PF_420;
    vState->ti.keyframe_granule_shift = i;

    vState->th = th_encode_alloc(&vState->ti);
    th_info_clear(&vState->ti);

    /* Header init */
    th_comment_init(&vState->tc);
    th_comment_add_tag(&vState->tc, (char *)"ENCODER", (char *)"rainbow");
    if (th_encode_flushheader(
        vState->th, &vState->tc, &vState->op) <= 0) {
        PR_LOG(log, PR_LOG_NOTICE, ("Internal Theora library error\n"));
        return NS_ERROR_FAILURE;
    }
    th_comment_clear(&vState->tc);

    ogg_stream_packetin(&vState->os, &vState->op);
    if (ogg_stream_pageout(&vState->os, &vState->og) != 1) {
        PR_LOG(log, PR_LOG_NOTICE, ("Internal Ogg library error\n"));
        return NS_ERROR_FAILURE;
    }

    rv = WriteData(vState->og.header, vState->og.header_len, &wr);
    rv = WriteData(vState->og.body, vState->og.body_len, &wr);

    return NS_OK;
}
Example #8
0
TheoraEnc* theoraenc_new (void) {
  
  TheoraEnc* enc = malloc (sizeof (TheoraEnc));

  if (enc == NULL) {
    printf ("ERROR: couldn't allocate encoder in theoraenc_new\n");
  }
  
  enc->info = malloc (sizeof (th_info));
  enc->comment = malloc (sizeof (th_comment));
  
  if (enc->info && enc->comment) {
    th_info_init (enc->info);
    th_comment_init (enc->comment);
  } else {
    printf ("ERROR: couldn't alloc info/comment in theoraenc_new\n");
    free (enc);
    return NULL;    
  }
  
  /* hardcodes based on the example gstreamer v4l2 -> theora pipeline settings */
  enc->info->frame_width = enc_frame_width;
  enc->info->frame_height = enc_frame_height;
  enc->info->pic_width = enc_pic_width;
  enc->info->pic_height = enc_pic_height;
  enc->info->fps_numerator = enc_fps_numerator;
  enc->info->fps_denominator = enc_fps_denominator;
  enc->info->quality = enc_quality;
  enc->info->target_bitrate = enc_target_bitrate;
  enc->info->keyframe_granule_shift = enc_keyframe_granule_shift;
  
  /* stuff that was already hardcoded in gstreamer's theora encoder */
  enc->info->aspect_numerator = 0;
  enc->info->aspect_denominator = 0;
  enc->info->pixel_fmt = TH_PF_420;
  enc->info->colorspace = TH_CS_UNSPECIFIED;
  
  enc->ctx = th_encode_alloc (enc->info);
  if (enc->ctx == NULL) {
    printf ("Couldn't make a theora context in theoraenc_new.\n");
    printf ("The most likely cause is specifying illegal theora encoder settings.\n");
    printf ("Check the libtheora th_info documentation.\n");
    free (enc);
    return NULL;
  }

  enc->postconv_buffer = calloc (PCONV_BUFFER_TOTAL_SIZE, (sizeof (unsigned char)));
  
  if (enc->postconv_buffer == NULL) {
    printf ("ERROR: couldn't alloc reserve buffer in theoraenc_new\n");
    free (enc);
    return NULL;
  }
  
  return enc;
}
Example #9
0
TheoraState::TheoraState(ogg_page* aBosPage) :
  OggCodecState(aBosPage, true),
  mSetup(0),
  mCtx(0),
  mPixelAspectRatio(0)
{
  MOZ_COUNT_CTOR(TheoraState);
  th_info_init(&mInfo);
  th_comment_init(&mComment);
}
Example #10
0
static gboolean
theora_enc_set_format (GstVideoEncoder * benc, GstVideoCodecState * state)
{
    GstTheoraEnc *enc = GST_THEORA_ENC (benc);
    GstVideoInfo *info = &state->info;

    enc->width = GST_VIDEO_INFO_WIDTH (info);
    enc->height = GST_VIDEO_INFO_HEIGHT (info);

    th_info_clear (&enc->info);
    th_info_init (&enc->info);
    /* Theora has a divisible-by-sixteen restriction for the encoded video size but
     * we can define a picture area using pic_width/pic_height */
    enc->info.frame_width = GST_ROUND_UP_16 (enc->width);
    enc->info.frame_height = GST_ROUND_UP_16 (enc->height);
    enc->info.pic_width = enc->width;
    enc->info.pic_height = enc->height;
    switch (GST_VIDEO_INFO_FORMAT (info)) {
    case GST_VIDEO_FORMAT_I420:
        enc->info.pixel_fmt = TH_PF_420;
        break;
    case GST_VIDEO_FORMAT_Y42B:
        enc->info.pixel_fmt = TH_PF_422;
        break;
    case GST_VIDEO_FORMAT_Y444:
        enc->info.pixel_fmt = TH_PF_444;
        break;
    default:
        g_assert_not_reached ();
    }

    enc->info.fps_numerator = enc->fps_n = GST_VIDEO_INFO_FPS_N (info);
    enc->info.fps_denominator = enc->fps_d = GST_VIDEO_INFO_FPS_D (info);
    enc->info.aspect_numerator = GST_VIDEO_INFO_PAR_N (info);
    enc->info.aspect_denominator = GST_VIDEO_INFO_PAR_D (info);

    enc->info.colorspace = TH_CS_UNSPECIFIED;

    /* Save input state */
    if (enc->input_state)
        gst_video_codec_state_unref (enc->input_state);
    enc->input_state = gst_video_codec_state_ref (state);

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

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

    return TRUE;
}
Example #11
0
nsTheoraState::nsTheoraState(ogg_page* aBosPage) :
  nsOggCodecState(aBosPage),
  mSetup(0),
  mCtx(0),
  mFrameDuration(0),
  mPixelAspectRatio(0)
{
  MOZ_COUNT_CTOR(nsTheoraState);
  th_info_init(&mInfo);
  th_comment_init(&mComment);
}
Example #12
0
static int
noop_test_info ()
{
  th_info ti;

  INFO ("+ Initializing th_info struct");
  th_info_init (&ti);

  INFO ("+ Clearing empty th_info struct");
  th_info_clear (&ti);

  return 0;
}
Example #13
0
/*****************************************************************************
 * OpenEncoder: probe the encoder and return score
 *****************************************************************************/
static int OpenEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;
    int i_quality;
    int t_flags;
    int max_enc_level = 0;
    int keyframe_freq_force = 64;
    ogg_packet header;
    int status;

    if( p_enc->fmt_out.i_codec != VLC_CODEC_THEORA &&
        !p_enc->obj.force )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the encoder's structure */
    if( ( p_sys = malloc(sizeof(encoder_sys_t)) ) == NULL )
        return VLC_ENOMEM;
    p_enc->p_sys = p_sys;

    p_enc->pf_encode_video = Encode;
    p_enc->fmt_in.i_codec = VLC_CODEC_I420;
    p_enc->fmt_out.i_codec = VLC_CODEC_THEORA;

    config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );

    i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
    if( i_quality > 10 ) i_quality = 10;
    if( i_quality < 0 ) i_quality = 0;

    th_info_init( &p_sys->ti );

    p_sys->ti.frame_width = p_enc->fmt_in.video.i_visible_width;
    p_sys->ti.frame_height = p_enc->fmt_in.video.i_visible_height;

    if( p_sys->ti.frame_width % 16 || p_sys->ti.frame_height % 16 )
    {
        /* Pictures from the transcoder should always have a pitch
         * which is a multiple of 16 */
        p_sys->ti.frame_width = (p_sys->ti.frame_width + 15) >> 4 << 4;
        p_sys->ti.frame_height = (p_sys->ti.frame_height + 15) >> 4 << 4;

        msg_Dbg( p_enc, "padding video from %dx%d to %dx%d",
                 p_enc->fmt_in.video.i_visible_width, p_enc->fmt_in.video.i_visible_height,
                 p_sys->ti.frame_width, p_sys->ti.frame_height );
    }
Example #14
0
static char *
theora_enc_get_supported_formats (void)
{
    th_enc_ctx *encoder;
    th_info info;
    struct
    {
        th_pixel_fmt pixelformat;
        const char *fourcc;
    } formats[] = {
        {
            TH_PF_420, "I420"
        }, {
            TH_PF_422, "Y42B"
        }, {
            TH_PF_444, "Y444"
        }
    };
    GString *string = NULL;
    guint i;

    th_info_init (&info);
    info.frame_width = 16;
    info.frame_height = 16;
    info.fps_numerator = 25;
    info.fps_denominator = 1;
    for (i = 0; i < G_N_ELEMENTS (formats); i++) {
        info.pixel_fmt = formats[i].pixelformat;

        encoder = th_encode_alloc (&info);
        if (encoder == NULL)
            continue;

        GST_LOG ("format %s is supported", formats[i].fourcc);
        th_encode_free (encoder);

        if (string == NULL) {
            string = g_string_new (formats[i].fourcc);
        } else {
            g_string_append (string, ", ");
            g_string_append (string, formats[i].fourcc);
        }
    }
    th_info_clear (&info);

    return string == NULL ? NULL : g_string_free (string, FALSE);
}
Example #15
0
static GstStateChangeReturn
theora_parse_change_state (GstElement * element, GstStateChange transition)
{
  GstTheoraParse *parse = GST_THEORA_PARSE (element);
  GstStateChangeReturn ret;
  gint i;

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      th_info_init (&parse->info);
      th_comment_init (&parse->comment);
      parse->send_streamheader = TRUE;
      parse->buffer_queue = g_queue_new ();
      parse->event_queue = g_queue_new ();
      parse->prev_keyframe = -1;
      parse->prev_frame = -1;
      parse->granule_offset = 0;
      break;
    default:
      break;
  }

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

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      th_info_clear (&parse->info);
      th_comment_clear (&parse->comment);
      theora_parse_clear_queue (parse);
      g_queue_free (parse->buffer_queue);
      g_queue_free (parse->event_queue);
      parse->buffer_queue = NULL;
      for (i = 0; i < 3; i++) {
        if (parse->streamheader[i]) {
          gst_buffer_unref (parse->streamheader[i]);
          parse->streamheader[i] = NULL;
        }
      }
      parse->streamheader_received = FALSE;
      break;
    default:
      break;
  }

  return ret;
}
Example #16
0
krad_theora_decoder_t *krad_theora_decoder_create(unsigned char *header1, int header1len, unsigned char *header2, int header2len, unsigned char *header3, int header3len) {

	krad_theora_decoder_t *krad_theora;
	
	krad_theora = calloc(1, sizeof(krad_theora_decoder_t));

	krad_theora->granulepos = -1;

	th_comment_init(&krad_theora->comment);
	th_info_init(&krad_theora->info);

	krad_theora->packet.packet = header1;
	krad_theora->packet.bytes = header1len;
	krad_theora->packet.b_o_s = 1;
	krad_theora->packet.packetno = 1;
	th_decode_headerin(&krad_theora->info, &krad_theora->comment, &krad_theora->setup_info, &krad_theora->packet);
	//printf("x is %d len is %d\n", x, header1len);

	krad_theora->packet.packet = header2;
	krad_theora->packet.bytes = header2len;
	krad_theora->packet.b_o_s = 0;
	krad_theora->packet.packetno = 2;
	th_decode_headerin(&krad_theora->info, &krad_theora->comment, &krad_theora->setup_info, &krad_theora->packet);
	//printf("x is %d len is %d\n", x, header2len);

	krad_theora->packet.packet = header3;
	krad_theora->packet.bytes = header3len;
	krad_theora->packet.packetno = 3;
	th_decode_headerin(&krad_theora->info, &krad_theora->comment, &krad_theora->setup_info, &krad_theora->packet);

	printf("Theora %dx%d %.02f fps video\n Encoded frame content is %dx%d with %dx%d offset\n",
		   krad_theora->info.frame_width, krad_theora->info.frame_height, 
		   (double)krad_theora->info.fps_numerator/krad_theora->info.fps_denominator,
		   krad_theora->info.pic_width, krad_theora->info.pic_height, krad_theora->info.pic_x, krad_theora->info.pic_y);


	krad_theora->decoder = th_decode_alloc(&krad_theora->info, krad_theora->setup_info);

	th_setup_free(krad_theora->setup_info);

	return krad_theora;

}
Example #17
0
static gboolean
theora_enc_start (GstVideoEncoder * benc)
{
    GstTheoraEnc *enc;

    GST_DEBUG_OBJECT (benc, "start: init theora");
    enc = GST_THEORA_ENC (benc);

    th_info_init (&enc->info);
    th_comment_init (&enc->comment);
    enc->packetno = 0;

    if (enc->multipass_mode >= MULTIPASS_MODE_FIRST_PASS) {
        GError *err = NULL;

        if (!enc->multipass_cache_file) {
            GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL), (NULL));
            return FALSE;
        }
        enc->multipass_cache_fd =
            g_io_channel_new_file (enc->multipass_cache_file,
                                   (enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS ? "w" : "r"), &err);

        if (enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS)
            enc->multipass_cache_adapter = gst_adapter_new ();

        if (!enc->multipass_cache_fd) {
            GST_ELEMENT_ERROR (enc, RESOURCE, OPEN_READ, (NULL),
                               ("Failed to open multipass cache file: %s", err->message));
            g_error_free (err);
            return FALSE;
        }

        g_io_channel_set_encoding (enc->multipass_cache_fd, NULL, NULL);
    }

    return TRUE;
}
Example #18
0
/* Generate a dummy encoder context for use in th_encode_ctl queries */
th_enc_ctx *dummy_encode_ctx(void)
{
    th_enc_ctx *ctx;
    th_info info;

    /* set the minimal video parameters */
    th_info_init(&info);
    info.frame_width=320;
    info.frame_height=240;
    info.fps_numerator=1;
    info.fps_denominator=1;

    /* allocate and initialize a context object */
    ctx = th_encode_alloc(&info);
    if (ctx == NULL) {
        fprintf(stderr, "Error allocating encoder context.\n");
    }

    /* clear the info struct */
    th_info_clear(&info);

    return ctx;
}
Example #19
0
IoTheoraInfo *IoTheoraInfo_proto(void *state)
{
	IoTheoraInfo *self = IoObject_new(state);
	IoObject_tag_(self, IoTheoraInfo_newTag(state));

	th_info* data = calloc(1, sizeof(th_info));
        th_info_init(data);
	IoObject_setDataPointer_(self, data);

	IoState_registerProtoWithFunc_(state, self, IoTheoraInfo_proto);

	{
		IoMethodTable methodTable[] = {
		{"frameWidth", IoTheoraInfo_frameWidth},
		{"frameHeight", IoTheoraInfo_frameHeight},
		{"frameRate", IoTheoraInfo_frameRate},
		{NULL, NULL},
		};
		IoObject_addMethodTable_(self, methodTable);
	}

	return self;
}
Example #20
0
/* Generate a dummy encoder context for use in th_encode_ctl queries
   Release with th_encode_free()
   This and the next routine from theora/examples/libtheora_info.c */
static th_enc_ctx *
dummy_encode_ctx (void)
{
  th_enc_ctx *ctx;
  th_info info;

  /* set the minimal video parameters */
  th_info_init (&info);
  info.frame_width = 320;
  info.frame_height = 240;
  info.fps_numerator = 1;
  info.fps_denominator = 1;

  /* allocate and initialize a context object */
  ctx = th_encode_alloc (&info);
  if (!ctx)
    GST_WARNING ("Failed to allocate dummy encoder context.");

  /* clear the info struct */
  th_info_clear (&info);

  return ctx;
}
Example #21
0
void
gobee_theora_resize(int w, int h, int _stride, int sock, struct sockaddr *addr,
    int addrlen)
{
  time_t stamp = time(NULL);

  th_info_init(&tinfo);
  th_comment_init(&tcmnt);

  tinfo.frame_width = w;
  tinfo.frame_height = h;
  tinfo.pic_width = w;
  tinfo.pic_height = h;
  tinfo.pic_y = 0;
  tinfo.pic_x = 0;
  tinfo.fps_numerator = 30;
  tinfo.fps_denominator = 1;
  tinfo.aspect_denominator = 1;
  tinfo.aspect_numerator = 1;
  tinfo.target_bitrate = 200000;
  tinfo.quality = 12;
  tinfo.colorspace = TH_CS_ITU_REC_470BG; //TH_CS_UNSPECIFIED;
  tinfo.pixel_fmt = TH_PF_420;
  tinfo.keyframe_granule_shift = 100;
  tcmnt.vendor = "qqq";

  // recreate encoder
  if (tctx)
    th_encode_free(tctx);
  tctx = th_encode_alloc(&tinfo);

  __gobee_yuv_resize(&s_ycbcr, w, h);
  printf("sending...\n");
  __gobee_theora_send_headers(sock, addr, addrlen, stamp);
  printf("sent...\n");

}
Example #22
0
static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
{
    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_sys->b_packetizer = b_packetizer;
    p_sys->b_has_headers = false;
    p_sys->i_pts = VLC_TICK_INVALID;
    p_sys->b_decoded_first_keyframe = false;
    p_sys->tcx = NULL;

    if( b_packetizer )
    {
        p_dec->fmt_out.i_codec = VLC_CODEC_THEORA;
        p_dec->pf_packetize = Packetize;
    }
    else
    {
        p_dec->fmt_out.i_codec = VLC_CODEC_I420;
        p_dec->pf_decode = DecodeVideo;
    }
    p_dec->pf_flush = Flush;

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

    return VLC_SUCCESS;
}
bool CHolly_Theora_Video::Start()
{
	m_bFrameWaiting = false;

	th_info thInfo;
	th_info_init( &thInfo );

	thInfo.frame_width				= Width();
	thInfo.frame_height				= Height();
	thInfo.pic_width				= Width();
	thInfo.pic_height				= Height();
	thInfo.pic_x					= 0;
	thInfo.pic_y					= 0;
	thInfo.colorspace				= TH_CS_ITU_REC_470BG;
	thInfo.pixel_fmt				= TH_PF_420; // TH_PF_444
	thInfo.target_bitrate			= BitRate() * 1024;
	thInfo.quality					= 42;
	thInfo.keyframe_granule_shift	= 6; // default value
	thInfo.fps_numerator			= FPS();
	thInfo.fps_denominator			= 1;
	thInfo.aspect_numerator			= 1;
	thInfo.aspect_denominator		= 1;

	m_Encoder = th_encode_alloc( &thInfo );
	if ( !m_Encoder )
	{
		return false;
	}

	th_info_clear( &thInfo );

	SetupFrame();
	WriteHeader();

	return true;
}
Example #24
0
static int
noop_test_decode ()
{
  th_info ti;
  th_dec_ctx *td;

  INFO ("+ Testing decoder context with null info and setup");
  td = th_decode_alloc(NULL, NULL);
  if (td != NULL)
    FAIL("td_decode_alloc accepted null info pointers");

  INFO ("+ Initializing th_info struct");
  th_info_init (&ti);

  INFO ("+ Testing decoder context with empty info and null setup");
  td = th_decode_alloc(&ti, NULL);
  if (td != NULL)
    FAIL("td_decode_alloc accepted null info pointers");

  INFO ("+ Clearing th_info struct");
  th_info_clear (&ti);

  return 0;
}
Example #25
0
krad_theora_decoder_t *
krad_theora_decoder_create (krad_codec_header_t *header) {

    krad_theora_decoder_t *krad_theora;

    krad_theora = calloc(1, sizeof(krad_theora_decoder_t));

    krad_theora->granulepos = -1;

    th_comment_init(&krad_theora->comment);
    th_info_init(&krad_theora->info);
    /*
      krad_theora->packet.packet = header->header[0];
      krad_theora->packet.bytes = header->header_size[0];
      krad_theora->packet.b_o_s = 1;
      krad_theora->packet.packetno = 1;
      th_decode_headerin (&krad_theora->info, &krad_theora->comment,
                          &krad_theora->setup_info, &krad_theora->packet);

      krad_theora->packet.packet = header->header[1];
      krad_theora->packet.bytes = header->header_size[1];
      krad_theora->packet.b_o_s = 0;
      krad_theora->packet.packetno = 2;
      th_decode_headerin (&krad_theora->info, &krad_theora->comment,
                          &krad_theora->setup_info, &krad_theora->packet);

      krad_theora->packet.packet = header->header[2];
      krad_theora->packet.bytes = header->header_size[2];
      krad_theora->packet.packetno = 3;
      th_decode_headerin (&krad_theora->info, &krad_theora->comment,
                          &krad_theora->setup_info, &krad_theora->packet);

      krad_theora->color_depth = PIX_FMT_YUV420P;
      if (krad_theora->info.pixel_fmt == TH_PF_422) {
        krad_theora->color_depth = PIX_FMT_YUV422P;
        printk ("Theora color depth 422");
      }
      if (krad_theora->info.pixel_fmt == TH_PF_444) {
        krad_theora->color_depth = PIX_FMT_YUV444P;
        printk ("Theora color depth 444");
      }
    */
    printk ("Theora %dx%d %.02f fps video\n Encoded frame content is %dx%d with %dx%d offset",
            krad_theora->info.frame_width, krad_theora->info.frame_height,
            (double)krad_theora->info.fps_numerator/krad_theora->info.fps_denominator,
            krad_theora->info.pic_width, krad_theora->info.pic_height,
            krad_theora->info.pic_x, krad_theora->info.pic_y);


    krad_theora->offset_y = krad_theora->info.pic_y;
    krad_theora->offset_x = krad_theora->info.pic_x;

    krad_theora->width = krad_theora->info.pic_width;
    krad_theora->height = krad_theora->info.pic_height;

    krad_theora->decoder = th_decode_alloc (&krad_theora->info,
                                            krad_theora->setup_info);

    th_setup_free(krad_theora->setup_info);

    return krad_theora;
}
Example #26
0
void VideoStreamPlaybackTheora::set_file(const String &p_file) {

	ERR_FAIL_COND(playing);
	ogg_packet op;
	th_setup_info *ts = NULL;

	file_name = p_file;
	if (file) {
		memdelete(file);
	}
	file = FileAccess::open(p_file, FileAccess::READ);
	ERR_FAIL_COND(!file);

#ifdef THEORA_USE_THREAD_STREAMING
	thread_exit = false;
	thread_eof = false;
	//pre-fill buffer
	int to_read = ring_buffer.space_left();
	int read = file->get_buffer(read_buffer.ptr(), to_read);
	ring_buffer.write(read_buffer.ptr(), read);

	thread = Thread::create(_streaming_thread, this);

#endif

	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 */
	th_comment_init(&tc);
	th_info_init(&ti);

	theora_eos = false;
	vorbis_eos = false;

	/* Ogg file open; parse the headers */
	/* Only interested in Vorbis/Theora streams */
	int stateflag = 0;

	int audio_track_skip = audio_track;

	while (!stateflag) {
		int ret = buffer_data();
		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 && th_decode_headerin(&ti, &tc, &ts, &op) >= 0) {
				/* it is theora */
				copymem(&to, &test, sizeof(test));
				theora_p = 1;
			} else if (!vorbis_p && vorbis_synthesis_headerin(&vi, &vc, &op) >= 0) {

				/* it is vorbis */
				if (audio_track_skip) {
					vorbis_info_clear(&vi);
					vorbis_comment_clear(&vc);
					ogg_stream_clear(&test);
					vorbis_info_init(&vi);
					vorbis_comment_init(&vc);

					audio_track_skip--;
				} else {
					copymem(&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");
				clear();
				return;
			}
			if (!th_decode_headerin(&ti, &tc, &ts, &op)) {
				fprintf(stderr, "Error parsing Theora stream headers; "
								"corrupt stream?\n");
				clear();
				return;
			}
			theora_p++;
		}

		/* 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");
				clear();
				return;
			}
			ret = vorbis_synthesis_headerin(&vi, &vc, &op);
			if (ret) {
				fprintf(stderr, "Error parsing Vorbis stream headers; corrupt stream?\n");
				clear();
				return;
			}
			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(); /* someone needs more data */
			if (ret == 0) {
				fprintf(stderr, "End of file while searching for codec headers.\n");
				clear();
				return;
			}
		}
	}

	/* and now we have it all.  initialize decoders */
	if (theora_p) {
		td = th_decode_alloc(&ti, ts);
		printf("Ogg logical stream %lx is Theora %dx%d %.02f fps",
				to.serialno, ti.pic_width, ti.pic_height,
				(double)ti.fps_numerator / ti.fps_denominator);
		px_fmt = ti.pixel_fmt;
		switch (ti.pixel_fmt) {
			case TH_PF_420: printf(" 4:2:0 video\n"); break;
			case TH_PF_422: printf(" 4:2:2 video\n"); break;
			case TH_PF_444: printf(" 4:4:4 video\n"); break;
			case TH_PF_RSVD:
			default:
				printf(" video\n  (UNKNOWN Chroma sampling!)\n");
				break;
		}
		if (ti.pic_width != ti.frame_width || ti.pic_height != ti.frame_height)
			printf("  Frame content is %dx%d with offset (%d,%d).\n",
					ti.frame_width, ti.frame_height, ti.pic_x, ti.pic_y);
		th_decode_ctl(td, TH_DECCTL_GET_PPLEVEL_MAX, &pp_level_max,
				sizeof(pp_level_max));
		pp_level = 0;
		th_decode_ctl(td, TH_DECCTL_SET_PPLEVEL, &pp_level, sizeof(pp_level));
		pp_inc = 0;

		int w;
		int h;
		w = (ti.pic_x + ti.frame_width + 1 & ~1) - (ti.pic_x & ~1);
		h = (ti.pic_y + ti.frame_height + 1 & ~1) - (ti.pic_y & ~1);
		size.x = w;
		size.y = h;

		texture->create(w, h, Image::FORMAT_RGBA8, Texture::FLAG_FILTER | Texture::FLAG_VIDEO_SURFACE);

	} else {
		/* tear down the partial theora setup */
		th_info_clear(&ti);
		th_comment_clear(&tc);
	}

	th_setup_free(ts);

	if (vorbis_p) {
		vorbis_synthesis_init(&vd, &vi);
		vorbis_block_init(&vd, &vb);
		fprintf(stderr, "Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
				vo.serialno, vi.channels, vi.rate);
		//_setup(vi.channels, vi.rate);

	} else {
		/* tear down the partial vorbis setup */
		vorbis_info_clear(&vi);
		vorbis_comment_clear(&vc);
	}

	playing = false;
	buffering = true;
	time = 0;
	audio_frames_wrote = 0;
};
Example #27
0
krad_theora_encoder_t *krad_theora_encoder_create (int width, int height,
        int fps_numerator,
        int fps_denominator,
        int color_depth,
        int quality) {

    krad_theora_encoder_t *krad_theora;

    krad_theora = calloc (1, sizeof(krad_theora_encoder_t));

    krad_theora->width = width;
    krad_theora->height = height;
    krad_theora->quality = quality;
    krad_theora->color_depth = color_depth;

    th_info_init (&krad_theora->info);
    th_comment_init (&krad_theora->comment);

    krad_theora->info.frame_width = krad_theora->width;
    if (krad_theora->width % 16) {
        krad_theora->info.frame_width += 16 - (krad_theora->width % 16);
    }
    krad_theora->info.frame_height = krad_theora->height;
    if (krad_theora->height % 16) {
        krad_theora->info.frame_height += 16 - (krad_theora->height % 16);
    }
    krad_theora->info.pic_width = krad_theora->width;
    krad_theora->info.pic_height = krad_theora->height;
    krad_theora->info.pic_x = 0;
    krad_theora->info.pic_y = 0;
    krad_theora->info.aspect_denominator = 1;
    krad_theora->info.aspect_numerator = 1;
    krad_theora->info.target_bitrate = 0;
    krad_theora->info.quality = krad_theora->quality;
    if (krad_theora->color_depth == PIX_FMT_YUV420P) {
        krad_theora->info.pixel_fmt = TH_PF_420;
    }
    if (krad_theora->color_depth == PIX_FMT_YUV422P) {
        krad_theora->info.pixel_fmt = TH_PF_422;
    }
    if (krad_theora->color_depth == PIX_FMT_YUV444P) {
        krad_theora->info.pixel_fmt = TH_PF_444;
    }
    krad_theora->keyframe_shift = krad_theora->info.keyframe_granule_shift;

    printk ("Loading Theora encoder version %s", th_version_string());
    printk ("Theora keyframe shift %d", krad_theora->keyframe_shift);

    krad_theora->info.fps_numerator = fps_numerator;
    krad_theora->info.fps_denominator = fps_denominator;
    //krad_theora->keyframe_distance = 30;

    krad_theora->encoder = th_encode_alloc (&krad_theora->info);

    //th_encode_ctl (krad_theora->encoder,
    //TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
    // &krad_theora->keyframe_distance, sizeof(int));
    //printk ("Theora keyframe max distance %u\n",
    //  krad_theora->keyframe_distance);

    /*
    if (strstr(krad_system_cpu_type(), "x86") == NULL) {
      //FOR ARM Realtime
      th_encode_ctl (krad_theora->encoder,
                     TH_ENCCTL_GET_SPLEVEL_MAX,
                     &krad_theora->speed,
                     sizeof(int));
      printk ("Theora encoder speed: %d quality: %d",
              krad_theora->speed, krad_theora->quality);
      th_encode_ctl (krad_theora->encoder, TH_ENCCTL_SET_SPLEVEL,
                     &krad_theora->speed, sizeof(int));
    } else {
      //FOR x86 Realtime
      th_encode_ctl (krad_theora->encoder,
                     TH_ENCCTL_GET_SPLEVEL_MAX,
                     &krad_theora->speed, sizeof(int));
      if ((krad_theora->width <= 1280) && (krad_theora->height <= 720)) {
        krad_theora->speed -= 1;
      }
      printk ("Theora encoder speed: %d quality: %d",
              krad_theora->speed, krad_theora->quality);
      th_encode_ctl (krad_theora->encoder,
                     TH_ENCCTL_SET_SPLEVEL,
                     &krad_theora->speed, sizeof(int));
    }
    */
    /*
      while (th_encode_flushheader ( krad_theora->encoder,
                                     &krad_theora->comment,
                                     &krad_theora->packet) > 0) {

        krad_theora->header_combined_size += krad_theora->packet.bytes;
        krad_theora->header[krad_theora->header_count] =
          malloc (krad_theora->packet.bytes);
        memcpy (krad_theora->header[krad_theora->header_count],
                krad_theora->packet.packet,
                krad_theora->packet.bytes);
        krad_theora->header_len[krad_theora->header_count] =
          krad_theora->packet.bytes;
        krad_theora->header_count++;

        //printk ("krad_theora_encoder_create th_encode_flushheader got
        // header packet %"PRIi64" which is %ld bytes\n",
        //    krad_theora->packet.packetno, krad_theora->packet.bytes);
      }

      //printk ("krad_theora_encoder_create Got %d header packets\n",
      //      krad_theora->header_count);

      krad_theora->header_combined = calloc (1, krad_theora->header_combined_size + 10);

      krad_theora->header_combined[0] = 0x02;
      krad_theora->header_combined_pos++;

      //printk ("main is %ld\n", vorbis->header_main.bytes);
      if (krad_theora->header_len[0] > 255) {
        failfast ("theora mainheader to long for code");
      }

      krad_theora->demented = krad_theora->header_len[0];
      krad_theora->header_combined[1] = (char)krad_theora->demented;
      krad_theora->header_combined_pos++;

      //printk ("comments is %ld\n", vorbis->header_comments.bytes);
      if (krad_theora->header_len[1] > 255) {
        failfast ("theora comments header to long for code");
      }

      krad_theora->demented = krad_theora->header_len[1];
      krad_theora->header_combined[2] = (char)krad_theora->demented;
      krad_theora->header_combined_pos++;

      krad_theora->header_combined_size += 3;

      memcpy (krad_theora->header_combined + krad_theora->header_combined_pos,
              krad_theora->header[0],
              krad_theora->header_len[0]);
      krad_theora->header_combined_pos += krad_theora->header_len[0];

      //printf("main is %ld bytes headerpos is  %d \n",
      //vorbis->header_main.bytes, vorbis->headerpos);

      memcpy (krad_theora->header_combined + krad_theora->header_combined_pos,
              krad_theora->header[1],
              krad_theora->header_len[1]);
      krad_theora->header_combined_pos += krad_theora->header_len[1];

      //printf("comments is %ld bytes headerpos is  %d \n",
      //vorbis->header_comments.bytes, vorbis->headerpos);

      memcpy (krad_theora->header_combined + krad_theora->header_combined_pos,
              krad_theora->header[2],
              krad_theora->header_len[2]);
      krad_theora->header_combined_pos += krad_theora->header_len[2];
      krad_theora->krad_codec_header.codec = THEORA;
      krad_theora->krad_codec_header.header[0] = krad_theora->header[0];
      krad_theora->krad_codec_header.header_size[0] = krad_theora->header_len[0];
      krad_theora->krad_codec_header.header[1] = krad_theora->header[1];
      krad_theora->krad_codec_header.header_size[1] = krad_theora->header_len[1];
      krad_theora->krad_codec_header.header[2] = krad_theora->header[2];
      krad_theora->krad_codec_header.header_size[2] = krad_theora->header_len[2];

      krad_theora->krad_codec_header.header_combined = krad_theora->header_combined;
      krad_theora->krad_codec_header.header_combined_size = krad_theora->header_combined_size;
      krad_theora->krad_codec_header.header_count = 3;

      krad_theora->ycbcr[0].stride =  krad_theora->info.frame_width;
      krad_theora->ycbcr[0].width =  krad_theora->info.frame_width;
      krad_theora->ycbcr[0].height =  krad_theora->info.frame_height;

      krad_theora->ycbcr[0].data = calloc(1, krad_theora->info.frame_width * krad_theora->info.frame_height);

      if (krad_theora->color_depth == PIX_FMT_YUV420P) {
        krad_theora->ycbcr[1].stride = krad_theora->info.frame_width / 2;
        krad_theora->ycbcr[1].width = krad_theora->info.frame_width / 2;
        krad_theora->ycbcr[1].height = krad_theora->info.frame_height / 2;
        krad_theora->ycbcr[2].stride = krad_theora->info.frame_width / 2;
        krad_theora->ycbcr[2].width = krad_theora->info.frame_width / 2;
        krad_theora->ycbcr[2].height = krad_theora->info.frame_height / 2;

        krad_theora->ycbcr[1].data = calloc(1, ((krad_theora->info.frame_width / 2) * (krad_theora->info.frame_height / 2)));
        krad_theora->ycbcr[2].data = calloc(1, ((krad_theora->info.frame_width / 2) * (krad_theora->info.frame_height / 2)));
      }
      if (krad_theora->color_depth == PIX_FMT_YUV422P) {
        krad_theora->ycbcr[1].stride = krad_theora->info.frame_width / 2;
        krad_theora->ycbcr[1].width =  krad_theora->info.frame_width / 2;
        krad_theora->ycbcr[1].height =  krad_theora->info.frame_height;
        krad_theora->ycbcr[2].stride = krad_theora->info.frame_width / 2;
        krad_theora->ycbcr[2].width = krad_theora->info.frame_width / 2;
        krad_theora->ycbcr[2].height =  krad_theora->info.frame_height;

        krad_theora->ycbcr[1].data = calloc(1, ((krad_theora->info.frame_width / 2) * krad_theora->info.frame_height));
        krad_theora->ycbcr[2].data = calloc(1, ((krad_theora->info.frame_width / 2) * krad_theora->info.frame_height));

      }
      if (krad_theora->color_depth == PIX_FMT_YUV444P) {
        krad_theora->ycbcr[1].stride = krad_theora->info.frame_width;
        krad_theora->ycbcr[1].width = krad_theora->info.frame_width;
        krad_theora->ycbcr[1].height = krad_theora->info.frame_height;
        krad_theora->ycbcr[2].stride = krad_theora->info.frame_width;
        krad_theora->ycbcr[2].width = krad_theora->info.frame_width;
        krad_theora->ycbcr[2].height = krad_theora->info.frame_height;

        krad_theora->ycbcr[1].data = calloc(1, krad_theora->info.frame_width * krad_theora->info.frame_height);
        krad_theora->ycbcr[2].data = calloc(1, krad_theora->info.frame_width * krad_theora->info.frame_height);
      }
    */
    return krad_theora;

}
Example #28
0
bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
	close();

	_fileStream = stream;

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

	// init supporting Vorbis structures needed in header parsing
	vorbis_info_init(&_vorbisInfo);
	vorbis_comment vorbisComment;
	vorbis_comment_init(&vorbisComment);

	// init supporting Theora structures needed in header parsing
	th_info theoraInfo;
	th_info_init(&theoraInfo);
	th_comment theoraComment;
	th_comment_init(&theoraComment);
	th_setup_info *theoraSetup = 0;

	uint theoraPackets = 0, vorbisPackets = 0;

	// Ogg file open; parse the headers
	// Only interested in Vorbis/Theora streams
	bool foundHeader = false;
	while (!foundHeader) {
		int ret = bufferData();

		if (ret == 0)
			break; // FIXME: Shouldn't this error out?

		while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) {
			ogg_stream_state test;

			// is this a mandated initial header? If not, stop parsing
			if (!ogg_page_bos(&_oggPage)) {
				// don't leak the page; get it into the appropriate stream
				queuePage(&_oggPage);
				foundHeader = true;
				break;
			}

			ogg_stream_init(&test, ogg_page_serialno(&_oggPage));
			ogg_stream_pagein(&test, &_oggPage);
			ogg_stream_packetout(&test, &_oggPacket);

			// identify the codec: try theora
			if (theoraPackets == 0 && th_decode_headerin(&theoraInfo, &theoraComment, &theoraSetup, &_oggPacket) >= 0) {
				// it is theora
				memcpy(&_theoraOut, &test, sizeof(test));
				theoraPackets = 1;
				_hasVideo = true;
			} else if (vorbisPackets == 0 && vorbis_synthesis_headerin(&_vorbisInfo, &vorbisComment, &_oggPacket) >= 0) {
				// it is vorbis
				memcpy(&_vorbisOut, &test, sizeof(test));
				vorbisPackets = 1;
				_hasAudio = true;
			} 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 ((theoraPackets && theoraPackets < 3) || (vorbisPackets && vorbisPackets < 3)) {
		int ret;

		// look for further theora headers
		while (theoraPackets && (theoraPackets < 3) && (ret = ogg_stream_packetout(&_theoraOut, &_oggPacket))) {
			if (ret < 0)
				error("Error parsing Theora stream headers; corrupt stream?");

			if (!th_decode_headerin(&theoraInfo, &theoraComment, &theoraSetup, &_oggPacket))
				error("Error parsing Theora stream headers; corrupt stream?");

			theoraPackets++;
		}

		// look for more vorbis header packets
		while (vorbisPackets && (vorbisPackets < 3) && (ret = ogg_stream_packetout(&_vorbisOut, &_oggPacket))) {
			if (ret < 0)
				error("Error parsing Vorbis stream headers; corrupt stream?");

			if (vorbis_synthesis_headerin(&_vorbisInfo, &vorbisComment, &_oggPacket))
				error("Error parsing Vorbis stream headers; corrupt stream?");

			vorbisPackets++;

			if (vorbisPackets == 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(&_oggSync, &_oggPage) > 0) {
			queuePage(&_oggPage); // demux into the appropriate stream
		} else {
			ret = bufferData(); // someone needs more data

			if (ret == 0)
				error("End of file while searching for codec headers.");
		}
	}

	// And now we have it all. Initialize decoders next
	if (_hasVideo) {
		_videoTrack = new TheoraVideoTrack(getDefaultHighColorFormat(), theoraInfo, theoraSetup);
		addTrack(_videoTrack);
	}

	th_info_clear(&theoraInfo);
	th_comment_clear(&theoraComment);
	th_setup_free(theoraSetup);

	if (_hasAudio) {
		_audioTrack = new VorbisAudioTrack(_soundType, _vorbisInfo);

		// Get enough audio data to start us off
		while (!_audioTrack->hasAudio()) {
			// Queue more data
			bufferData();
			while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0)
				queuePage(&_oggPage);

			queueAudio();
		}

		addTrack(_audioTrack);
	}

	vorbis_comment_clear(&vorbisComment);

	return true;
}
Example #29
0
    void writeTheora(std::vector<std::vector<uint8_t>> vidframes, std::string writeTo, uint16_t vidWidth, uint16_t vidHeight) {
        // get paddings to nearest multiple of 0x10
        uint32_t padW = 16 - vidWidth % 16;
        uint32_t padH = 16 - vidHeight % 16;
        uint32_t frmWidth = vidWidth + padW;
        uint32_t frmHeight = vidHeight + padH;

        // initialize theora stream
        th_info vidinfo;
        th_info_init(&vidinfo);
        vidinfo.frame_width     = frmWidth;
        vidinfo.frame_height    = frmHeight;
        vidinfo.pic_width       = vidWidth;
        vidinfo.pic_height      = vidHeight;
        vidinfo.pic_x           = 0;
        vidinfo.pic_y           = 0;
        vidinfo.colorspace      = TH_CS_ITU_REC_470M; // what our RGB->YCbCr function operates on
        vidinfo.pixel_fmt       = TH_PF_444;          // we want the bestest video possible, so no decimation
        vidinfo.target_bitrate  = 0;                  // prefer VBR with quality level...
        vidinfo.quality         = 63;                 // ...which we want as high as possible (since we aren't using photographic frames, lossy compression ruins things)
        vidinfo.fps_numerator   = 15;                 // framerate is 15 fps
        vidinfo.fps_denominator = 1;

        // initialize theora encoding context
        th_enc_ctx * videnc = th_encode_alloc(&vidinfo);

        // initialize theora comment
        th_comment vidcomment;
        th_comment_init(&vidcomment);

        // initialize ogg container
        ogg_stream_state vidcont;
        // serial number chosen by fair dice roll
        if (ogg_stream_init(&vidcont, 42)) { // returned -1, thus failed
            std::cerr << "Failed to initialize ogg container :(\n";
            throw 42;
        }

        // get generic ogg packet & page holders
        ogg_packet vidpacket;
        ogg_page vidpage;

        // generic YCbCr frame, and initial data
        const int Y = 0;
        const int Cb = 1;
        const int Cr = 2; // clarity bonuses
        th_ycbcr_buffer rawdata;
        for (auto & i : rawdata) {
            i.width = i.stride = frmWidth;
            i.height = frmHeight;
            i.data = new unsigned char [frmWidth * frmHeight];
        }
        

        // open file for writing
        std::ofstream vidfile; // because god forbid this thing supports an unsigned char unit
        vidfile.open(writeTo, std::ios::binary);

        // factor out the ogg page writing process a bit
        auto writePage = [&](){
            vidfile.write((char*)vidpage.header, vidpage.header_len);
            if (!vidfile) {
                std::cerr << "An error occured in writing Ogg page header to file. Exiting...\n";
                vidfile.close();
                throw 42;
            }

            vidfile.write((char*)vidpage.body, vidpage.body_len);
            if (!vidfile) {
                std::cerr << "An error occured in writing Ogg page body to file. Exiting...\n";
                vidfile.close();
                throw 42;
            }
        };




        // send header packets to ogg stream
        bool gotone = false;
        while (true) {
            int mkpacket = th_encode_flushheader(videnc, &vidcomment, &vidpacket);
            if (mkpacket == 0) {
                if (gotone) {
                    break;
                } else {
                    std::cerr << "Theora didn't return any header packets.\n";
                    throw 42;
                }
            }

            if (mkpacket < 0) {
                std::cerr << "Theora header flushing failed with error code " << mkpacket << ". Exiting...\n";
                throw 42;
            }

            if (ogg_stream_packetin(&vidcont, &vidpacket)) {
                std::cerr << "Giving packet to Ogg failed, sorry.\n";
                throw 42;
            }

            gotone = true;
        }

        // write ogg pages (and then the remainder via flush) to file
        while (ogg_stream_pageout(&vidcont, &vidpage)) {
            writePage();
        }

        while (ogg_stream_flush(&vidcont, &vidpage)) {
            writePage();
        }

        //////////////////////
        // WRITE THE FRAMES //
        //////////////////////

        for (int FRNO = 0; FRNO < vidframes.size(); FRNO++) {
            auto * VFR = &vidframes.at(FRNO);
            // since we set an offset of (0,0) for the picture, we fill up the
            // top and right edges of the frame with junk. This is us filling
            // the top part
            for (int i = 0; i < padH; i++) {
                for (int j = 0; j < frmWidth; j++) {
                    rawdata[Y].data[i * frmWidth + j] = 0;
                    rawdata[Cb].data[i * frmWidth + j] = 0;
                    rawdata[Cr].data[i * frmWidth + j] = 0;
                }
            }

            // now for the picture itself (every row we add more junk to the right
            // of the image)
            int vecAt = 0; // where we are in the VFR vector
            for (int i = 0; i < vidHeight; i++) {
                for (int j = 0; j < vidWidth; j++) {
                    rawdata[Y].data[i * frmWidth + j]  = VFR->at(vecAt); vecAt++;
                    rawdata[Cb].data[i * frmWidth + j] = VFR->at(vecAt); vecAt++;
                    rawdata[Cr].data[i * frmWidth + j] = VFR->at(vecAt); vecAt++;
                }

                // get right-side padding (fill with junk)
                for (int j = vidWidth; j < frmWidth; j++) {
                    rawdata[Y].data[i * frmWidth + j]  = 0;
                    rawdata[Cb].data[i * frmWidth + j] = 0;
                    rawdata[Cr].data[i * frmWidth + j] = 0;
                }
            }

            // frame made, send through theora
            if (th_encode_ycbcr_in(videnc, rawdata)) {
                std::cerr << "Error in sending frame " << FRNO + 1 << " of " << vidframes.size() << " to Theora.\n";
                throw 42;
            }

            // send theora packets into ogg
            while (true) {
                int packok = th_encode_packetout(videnc, FRNO + 1 == vidframes.size(), &vidpacket);
                if (packok == 0) { break; }
                if (packok < 0) {
                    std::cerr << "Retrieving packet from Theora failed with error code " << packok << ".\n";
                    throw 42;
                }

                if (ogg_stream_packetin(&vidcont, &vidpacket)) {
                    std::cerr << "Giving frame packet to Ogg failed.\n";
                    throw 42;
                }
            }

            // send complete pages from frame to file (we won't flush until
            // after all frames are accounted for, to avoid an abundance of
            // undersized pages)

            while (ogg_stream_pageout(&vidcont, &vidpage)) {
                writePage();
            }
        }

        // take care of any remaining undersized page(s)

        while (ogg_stream_flush(&vidcont, &vidpage)) {
            writePage();
        }

        //// Free/close/etc all relevant structures

        // fstream
        vidfile.close();

        // theora items
        //th_encode_free(videnc); // causes a corrupted double-linked list, somehow, so you'll have to live with unfree'd memory :(
        th_info_clear(&vidinfo);
        th_comment_clear(&vidcomment);

        for (auto & i : rawdata) {
            delete[] i.data;
        }

        // ogg items
        ogg_packet_clear(&vidpacket);
        ogg_stream_clear(&vidcont);
    }
Example #30
0
static av_cold int encode_init(AVCodecContext* avc_context)
{
    th_info t_info;
    th_comment t_comment;
    ogg_packet o_packet;
    unsigned int offset;
    TheoraContext *h = avc_context->priv_data;
    uint32_t gop_size = avc_context->gop_size;

    /* Set up the theora_info struct */
    th_info_init(&t_info);
    t_info.frame_width  = FFALIGN(avc_context->width,  16);
    t_info.frame_height = FFALIGN(avc_context->height, 16);
    t_info.pic_width    = avc_context->width;
    t_info.pic_height   = avc_context->height;
    t_info.pic_x        = 0;
    t_info.pic_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) {
        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;
    }

    if (avc_context->color_primaries == AVCOL_PRI_BT470M)
        t_info.colorspace = TH_CS_ITU_REC_470M;
    else if (avc_context->color_primaries == AVCOL_PRI_BT470BG)
        t_info.colorspace = TH_CS_ITU_REC_470BG;
    else
        t_info.colorspace = TH_CS_UNSPECIFIED;

    if (avc_context->pix_fmt == AV_PIX_FMT_YUV420P)
        t_info.pixel_fmt = TH_PF_420;
    else if (avc_context->pix_fmt == AV_PIX_FMT_YUV422P)
        t_info.pixel_fmt = TH_PF_422;
    else if (avc_context->pix_fmt == AV_PIX_FMT_YUV444P)
        t_info.pixel_fmt = TH_PF_444;
    else {
        av_log(avc_context, AV_LOG_ERROR, "Unsupported pix_fmt\n");
        return -1;
    }
    av_pix_fmt_get_chroma_sub_sample(avc_context->pix_fmt,
                                     &h->uv_hshift, &h->uv_vshift);

    if (avc_context->flags & CODEC_FLAG_QSCALE) {
        /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10
           Theora accepts a quality parameter p, which is:
                * 0 <= p <=63
                * an int value
         */
        t_info.quality        = av_clipf(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3;
        t_info.target_bitrate = 0;
    } else {
        t_info.target_bitrate = avc_context->bit_rate;
        t_info.quality        = 0;
    }

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

    h->keyframe_mask = (1 << t_info.keyframe_granule_shift) - 1;
    /* Clear up theora_info struct */
    th_info_clear(&t_info);

    if (th_encode_ctl(h->t_state, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
                      &gop_size, sizeof(gop_size))) {
        av_log(avc_context, AV_LOG_ERROR, "Error setting GOP size\n");
        return -1;
    }

    // need to enable 2 pass (via TH_ENCCTL_2PASS_) before encoding headers
    if (avc_context->flags & CODEC_FLAG_PASS1) {
        if (get_stats(avc_context, 0))
            return -1;
    } else if (avc_context->flags & CODEC_FLAG_PASS2) {
        if (submit_stats(avc_context))
            return -1;
    }

    /*
        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 libavcodec's extradata.
    */
    offset = 0;

    /* Headers */
    th_comment_init(&t_comment);

    while (th_encode_flushheader(h->t_state, &t_comment, &o_packet))
        if (concatenate_packet(&offset, avc_context, &o_packet))
            return -1;

    th_comment_clear(&t_comment);

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

    return 0;
}