int encx265Work(hb_work_object_t *w, hb_buffer_t **buf_in, hb_buffer_t **buf_out) { hb_work_private_t *pv = w->private_data; hb_buffer_t *in = *buf_in; if (in->s.flags & HB_BUF_FLAG_EOF) { uint32_t nnal; x265_nal *nal; x265_picture pic_out; hb_buffer_list_t list; hb_buffer_list_clear(&list); // flush delayed frames while (pv->api->encoder_encode(pv->x265, &nal, &nnal, NULL, &pic_out) > 0) { hb_buffer_t *buf = nal_encode(w, &pic_out, nal, nnal); hb_buffer_list_append(&list, buf); } // add the EOF to the end of the chain hb_buffer_list_append(&list, in); *buf_out = hb_buffer_list_clear(&list); *buf_in = NULL; return HB_WORK_DONE; } *buf_out = x265_encode(w, in); return HB_WORK_OK; }
/* * Decodes a single SSA packet to one or more TEXTSUB or PICTURESUB subtitle packets. * * SSA packet format: * ( Dialogue: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text CR LF ) + * 1 2 3 4 5 6 7 8 9 10 */ static hb_buffer_t *ssa_decode_packet( hb_work_object_t * w, hb_buffer_t *in ) { // Store NULL after the end of the buffer to make using string processing safe hb_buffer_realloc(in, ++in->size); in->data[in->size - 1] = '\0'; hb_buffer_list_t list; hb_buffer_t *buf; hb_buffer_list_clear(&list); const char *EOL = "\r\n"; char *curLine, *curLine_parserData; for ( curLine = strtok_r( (char *) in->data, EOL, &curLine_parserData ); curLine; curLine = strtok_r( NULL, EOL, &curLine_parserData ) ) { // Skip empty lines and spaces between adjacent CR and LF if (curLine[0] == '\0') continue; // Decode an individual SSA line buf = ssa_decode_line_to_mkv_ssa(w, in, (uint8_t *)curLine, strlen(curLine)); hb_buffer_list_append(&list, buf); } return hb_buffer_list_clear(&list); }
/*********************************************************************** * Work *********************************************************************** * **********************************************************************/ static int encavcodecaWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_t ** buf_out ) { hb_work_private_t * pv = w->private_data; hb_buffer_t * in = *buf_in, * buf; hb_buffer_list_t list; if (in->s.flags & HB_BUF_FLAG_EOF) { /* EOF on input - send it downstream & say we're done */ *buf_out = Flush( w ); return HB_WORK_DONE; } if ( pv->context == NULL || pv->context->codec == NULL ) { // No encoder context. Nothing we can do. return HB_WORK_OK; } hb_list_add( pv->list, in ); *buf_in = NULL; hb_buffer_list_clear(&list); buf = Encode( w ); while (buf != NULL) { hb_buffer_list_append(&list, buf); buf = Encode( w ); } *buf_out = hb_buffer_list_clear(&list); return HB_WORK_OK; }
/*********************************************************************** * Work *********************************************************************** * **********************************************************************/ int encvorbisWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_t ** buf_out ) { hb_work_private_t * pv = w->private_data; hb_buffer_t * in = *buf_in; hb_buffer_t * buf; hb_buffer_list_t list; *buf_in = NULL; hb_buffer_list_clear(&list); if (in->s.flags & HB_BUF_FLAG_EOF) { /* EOF on input - send it downstream & say we're done */ *buf_out = in; return HB_WORK_DONE; } hb_list_add(pv->list, in); buf = Encode( w ); while (buf) { hb_buffer_list_append(&list, buf); buf = Encode( w ); } *buf_out = hb_buffer_list_clear(&list); return HB_WORK_OK; }
static hb_buffer_t * splice_discontinuity( hb_work_private_t *r, hb_buffer_t *buf ) { // Handle buffers that were split across a PCR discontinuity. // Rejoin them into a single buffer. hb_buffer_list_t * list = get_splice_list(r, buf->s.id); if (list != NULL) { hb_buffer_list_append(list, buf); if (buf->s.split) { return NULL; } int count = hb_buffer_list_count(list); if (count > 1) { int size = hb_buffer_list_size(list); hb_buffer_t * b = hb_buffer_init(size); buf = hb_buffer_list_head(list); b->s = buf->s; int pos = 0; while ((buf = hb_buffer_list_rem_head(list)) != NULL) { memcpy(b->data + pos, buf->data, buf->size); pos += buf->size; hb_buffer_close(&buf); } buf = b; } else { buf = hb_buffer_list_clear(list); } } return buf; }
static hb_buffer_t* Encode(hb_work_object_t *w) { hb_work_private_t *pv = w->private_data; hb_audio_t *audio = w->audio; uint64_t pts, pos; if (hb_list_bytes(pv->list) < pv->input_samples * sizeof(float)) { return NULL; } hb_list_getbytes(pv->list, pv->input_buf, pv->input_samples * sizeof(float), &pts, &pos); // Prepare input frame int out_linesize; int out_size = av_samples_get_buffer_size(&out_linesize, pv->context->channels, pv->samples_per_frame, pv->context->sample_fmt, 1); AVFrame frame = { .nb_samples = pv->samples_per_frame, }; avcodec_fill_audio_frame(&frame, pv->context->channels, pv->context->sample_fmt, pv->output_buf, out_size, 1); if (pv->avresample != NULL) { int in_linesize; av_samples_get_buffer_size(&in_linesize, pv->context->channels, frame.nb_samples, AV_SAMPLE_FMT_FLT, 1); int out_samples = avresample_convert(pv->avresample, frame.extended_data, out_linesize, frame.nb_samples, &pv->input_buf, in_linesize, frame.nb_samples); if (out_samples != pv->samples_per_frame) { // we're not doing sample rate conversion, so this shouldn't happen hb_log("encavcodecaWork: avresample_convert() failed"); return NULL; } } // Libav requires that timebase of audio frames be in sample_rate units frame.pts = pts + (90000 * pos / (sizeof(float) * pv->out_discrete_channels * audio->config.out.samplerate)); frame.pts = av_rescale(frame.pts, pv->context->sample_rate, 90000); // Prepare output packet AVPacket pkt; int got_packet; hb_buffer_t *out = hb_buffer_init(pv->max_output_bytes); av_init_packet(&pkt); pkt.data = out->data; pkt.size = out->alloc; // Encode int ret = avcodec_encode_audio2(pv->context, &pkt, &frame, &got_packet); if (ret < 0) { hb_log("encavcodeca: avcodec_encode_audio failed"); hb_buffer_close(&out); return NULL; } if (got_packet && pkt.size) { out->size = pkt.size; // The output pts from libav is in context->time_base. Convert it back // to our timebase. out->s.start = av_rescale_q(pkt.pts, pv->context->time_base, (AVRational){1, 90000}); out->s.duration = (double)90000 * pv->samples_per_frame / audio->config.out.samplerate; out->s.stop = out->s.start + out->s.duration; out->s.type = AUDIO_BUF; out->s.frametype = HB_FRAME_AUDIO; } else { hb_buffer_close(&out); return Encode(w); } return out; } static hb_buffer_t * Flush( hb_work_object_t * w ) { hb_buffer_list_t list; hb_buffer_t *buf; hb_buffer_list_clear(&list); buf = Encode( w ); while (buf != NULL) { hb_buffer_list_append(&list, buf); buf = Encode( w ); } hb_buffer_list_append(&list, hb_buffer_eof_init()); return hb_buffer_list_clear(&list); }