From: David F. <dav...@wo...> - 2008-07-19 22:37:55
|
This is a quick work-in-progress for fixing gstschroenc's timestamp handling. I'll post a commentry in a followup. This example also includes my reworked granule pos (which i'm still to poke xiph about) ..david diff --git a/schroedinger/schroencoder.c b/schroedinger/schroencoder.c index 8c64a5c..5f523f7 100644 --- a/schroedinger/schroencoder.c +++ b/schroedinger/schroencoder.c @@ -484,6 +484,10 @@ schro_encoder_pull_full (SchroEncoder *encoder, int *presentation_frame, SCHRO_DEBUG("pulling slot %d", encoder->output_slot); + if (priv) { + *priv = NULL; + } + schro_async_lock (encoder->async); for(i=0;i<encoder->frame_queue->n;i++){ SchroEncoderFrame *frame; @@ -493,7 +497,7 @@ schro_encoder_pull_full (SchroEncoder *encoder, int *presentation_frame, int is_picture = FALSE; if (presentation_frame) { - *presentation_frame = frame->presentation_frame; + *presentation_frame = frame->frame_number; } if (frame->sequence_header_buffer) { buffer = frame->sequence_header_buffer; diff --git a/gst/gstschroenc.c b/gst/gstschroenc.c index 7cb0535..f88acf7 100644 --- a/gst/gstschroenc.c +++ b/gst/gstschroenc.c @@ -69,14 +69,11 @@ struct _GstSchroEnc gint64 segment_position; /* state */ - gboolean got_offset; - gboolean update_granulepos; - uint64_t granulepos_offset; - uint64_t granulepos_low; - uint64_t granulepos_hi; gboolean started; - gint64 timestamp_offset; - int picture_number; + /* all of this tat is for ogg */ + uint32_t num_coded_pics; /* number of codec pictures output */ + uint32_t last_sync_dpn; /* last picnum (in display order) that is a sync point */ + uint32_t last_sync_cpn; /* value of num_coded_pictures at last sync point */ SchroEncoder *encoder; SchroVideoFormat *video_format; @@ -87,6 +84,12 @@ struct _GstSchroEncClass GstElementClass parent_class; }; +/* private structure passed through encoder from input picture + * to output coded bits */ +struct _GstSchroEncFrameTag +{ + GstClockTime pts; +}; enum { @@ -673,19 +676,6 @@ gst_schro_enc_chain (GstPad *pad, GstBuffer *buf) GST_DEBUG("dropping early buffer"); return GST_FLOW_OK; } - if (!schro_enc->got_offset) { - schro_enc->granulepos_offset = - gst_util_uint64_scale (GST_BUFFER_TIMESTAMP(buf), schro_enc->fps_n, - GST_SECOND * schro_enc->fps_d); - - GST_DEBUG("using granulepos offset %lld", schro_enc->granulepos_offset); - schro_enc->granulepos_hi = 0; - schro_enc->granulepos_low = 0; - schro_enc->got_offset = TRUE; - - schro_enc->timestamp_offset = GST_BUFFER_TIMESTAMP(buf); - schro_enc->picture_number = 0; - } if (!schro_enc->started) { schro_encoder_start (schro_enc->encoder); schro_enc->started = TRUE; @@ -693,8 +683,11 @@ gst_schro_enc_chain (GstPad *pad, GstBuffer *buf) frame = gst_schro_buffer_wrap (schro_enc, buf, schro_enc->width, schro_enc->height); - GST_DEBUG ("pushing frame"); - schro_encoder_push_frame (schro_enc->encoder, frame); + struct _GstSchroEncFrameTag *tag = malloc(sizeof(struct _GstSchroEncFrameTag)); + tag->pts = GST_BUFFER_TIMESTAMP(buf); + + GST_DEBUG ("pushing frame timestamp=%lld", tag->pts); + schro_encoder_push_frame_full (schro_enc->encoder, frame, tag); ret = gst_schro_enc_process (schro_enc); @@ -711,6 +704,7 @@ gst_schro_enc_process (GstSchroEnc *schro_enc) GstFlowReturn ret; int presentation_frame; int parse_code; + void *tag; while (1) { switch (schro_encoder_wait (schro_enc->encoder)) { @@ -718,8 +712,9 @@ gst_schro_enc_process (GstSchroEnc *schro_enc) case SCHRO_STATE_END_OF_STREAM: return GST_FLOW_OK; case SCHRO_STATE_HAVE_BUFFER: - encoded_buffer = schro_encoder_pull (schro_enc->encoder, - &presentation_frame); + tag = NULL; + encoded_buffer = schro_encoder_pull_full (schro_enc->encoder, + &presentation_frame, &tag); if (encoded_buffer == NULL) { GST_ERROR("encoder_pull returned NULL"); /* FIXME This shouldn't happen */ @@ -728,16 +723,8 @@ gst_schro_enc_process (GstSchroEnc *schro_enc) parse_code = encoded_buffer->data[4]; if (SCHRO_PARSE_CODE_IS_SEQ_HEADER(parse_code)) { - schro_enc->update_granulepos = TRUE; - } - if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) { - if (schro_enc->update_granulepos) { - schro_enc->granulepos_hi = schro_enc->granulepos_offset + - presentation_frame + 1; - schro_enc->update_granulepos = FALSE; - } - schro_enc->granulepos_low = schro_enc->granulepos_offset + - presentation_frame + 1 - schro_enc->granulepos_hi; + schro_enc->last_sync_dpn = presentation_frame; + schro_enc->last_sync_cpn = schro_enc->num_coded_pics; } outbuf = gst_buffer_new_and_alloc (encoded_buffer->length); @@ -745,19 +732,19 @@ gst_schro_enc_process (GstSchroEnc *schro_enc) encoded_buffer->length); gst_buffer_set_caps (outbuf, GST_PAD_CAPS (schro_enc->srcpad)); - GST_BUFFER_OFFSET_END (outbuf) = - (schro_enc->granulepos_hi<<OGG_DIRAC_GRANULE_SHIFT) + - schro_enc->granulepos_low; - GST_BUFFER_OFFSET (outbuf) = gst_util_uint64_scale ( - (schro_enc->granulepos_hi + schro_enc->granulepos_low), - schro_enc->fps_d * GST_SECOND, schro_enc->fps_n); + /* ogg uses offset_end as granulepos (urgh!) */ + uint16_t dist = schro_enc->num_coded_pics - schro_enc->last_sync_cpn; + uint32_t sync_off = presentation_frame - schro_enc->last_sync_dpn; + uint32_t gp_hi = (sync_off << 16) | dist; + uint32_t gp_low = presentation_frame - gp_hi; + GST_BUFFER_OFFSET_END (outbuf) = ((uint64_t) gp_hi << 32) | gp_low; + GST_BUFFER_OFFSET (outbuf) = schro_enc->num_coded_pics; + if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) { + schro_enc->num_coded_pics++; GST_BUFFER_DURATION (outbuf) = schro_enc->duration; - GST_BUFFER_TIMESTAMP (outbuf) = - schro_enc->timestamp_offset + gst_util_uint64_scale ( - schro_enc->picture_number, - schro_enc->fps_d * GST_SECOND, schro_enc->fps_n); - schro_enc->picture_number++; + GST_BUFFER_TIMESTAMP (outbuf) = ((struct _GstSchroEncFrameTag*)tag)->pts; + if (!SCHRO_PARSE_CODE_IS_INTRA(parse_code)) { GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); } else { @@ -765,14 +752,11 @@ gst_schro_enc_process (GstSchroEnc *schro_enc) } } else { GST_BUFFER_DURATION (outbuf) = -1; - GST_BUFFER_TIMESTAMP (outbuf) = - schro_enc->timestamp_offset + gst_util_uint64_scale ( - schro_enc->picture_number, - schro_enc->fps_d * GST_SECOND, schro_enc->fps_n); + GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); } - GST_INFO("size %d offset %lld granulepos %llu:%llu timestamp %lld duration %lld", + GST_INFO("size %d offset %lld granulepos %ll08x:%ll08x timestamp %lld duration %lld", GST_BUFFER_SIZE (outbuf), GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf)>>OGG_DIRAC_GRANULE_SHIFT, @@ -780,6 +764,9 @@ gst_schro_enc_process (GstSchroEnc *schro_enc) GST_BUFFER_TIMESTAMP (outbuf), GST_BUFFER_DURATION (outbuf)); + if (tag) + free(tag); + schro_buffer_unref (encoded_buffer); ret = gst_pad_push (schro_enc->srcpad, outbuf); |