/* prepare a buffer for transmission by passing data through libvorbis */ static GstBuffer * gst_vorbis_enc_buffer_from_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet) { GstBuffer *outbuf; outbuf = gst_buffer_new_and_alloc (packet->bytes); memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes); /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its * time representation */ GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos + vorbisenc->granulepos_offset; GST_BUFFER_OFFSET (outbuf) = granulepos_to_timestamp (vorbisenc, GST_BUFFER_OFFSET_END (outbuf)); GST_BUFFER_TIMESTAMP (outbuf) = vorbisenc->next_ts; /* update the next timestamp, taking granulepos_offset and subgranule offset * into account */ vorbisenc->next_ts = granulepos_to_timestamp_offset (vorbisenc, packet->granulepos); GST_BUFFER_DURATION (outbuf) = vorbisenc->next_ts - GST_BUFFER_TIMESTAMP (outbuf); if (vorbisenc->next_discont) { GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); vorbisenc->next_discont = FALSE; } GST_LOG_OBJECT (vorbisenc, "encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf)); return outbuf; }
/* prepare a buffer for transmission by passing data through libtheora */ static GstFlowReturn theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet, GstClockTime timestamp, GstClockTime running_time, GstClockTime duration, GstBuffer ** buffer) { GstBuffer *buf; GstFlowReturn ret = GST_FLOW_OK; buf = gst_buffer_new_and_alloc (packet->bytes); if (!buf) { GST_WARNING_OBJECT (enc, "Could not allocate buffer"); ret = GST_FLOW_ERROR; goto done; } memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes); gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad)); /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its * time representation */ GST_BUFFER_OFFSET_END (buf) = granulepos_add (packet->granulepos, enc->granulepos_offset, enc->granule_shift); GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc, GST_BUFFER_OFFSET_END (buf)); GST_BUFFER_TIMESTAMP (buf) = timestamp; GST_BUFFER_DURATION (buf) = duration; if (enc->next_discont) { GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); enc->next_discont = FALSE; } /* the second most significant bit of the first data byte is cleared * for keyframes */ if ((packet->packet[0] & 0x40) == 0) { GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT); } else { GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); } enc->packetno++; done: *buffer = buf; return ret; }
static GstFlowReturn theora_enc_pre_push (GstVideoEncoder * benc, GstVideoCodecFrame * frame) { GstTheoraEnc *enc = GST_THEORA_ENC (benc); guint64 pfn; /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its * time representation */ /* granulepos from sync frame */ pfn = frame->presentation_frame_number - frame->distance_from_sync; /* correct to correspond to linear running time */ pfn -= enc->pfn_offset; pfn += enc->granulepos_offset + 1; /* granulepos */ GST_BUFFER_OFFSET_END (frame->output_buffer) = (pfn << enc->info.keyframe_granule_shift) + frame->distance_from_sync; GST_BUFFER_OFFSET (frame->output_buffer) = granulepos_to_timestamp (enc, GST_BUFFER_OFFSET_END (frame->output_buffer)); return GST_FLOW_OK; }