static int send_packet(struct videnc_state *ves, bool marker, const uint8_t *pld, size_t pld_len) { daala_packet dp; int err; memset(&dp, 0, sizeof(dp)); dp.packet = (uint8_t *)pld; dp.bytes = pld_len; dp.b_o_s = marker; err = ves->pkth(marker, NULL, 0, pld, pld_len, ves->arg); if (err) return err; ++ves->stats.n_packet; ++ves->stats.valid; if (daala_packet_isheader(&dp)) ++ves->stats.n_header; else if (daala_packet_iskeyframe(&dp) > 0) ++ves->stats.n_keyframe; return 0; }
static block_t *Encode( encoder_t *p_enc, picture_t *p_pict ) { encoder_sys_t *p_sys = p_enc->p_sys; ogg_packet oggpacket; block_t *p_block; od_img img; if( !p_pict ) return NULL; const int i_width = p_sys->di.pic_width; const int i_height = p_sys->di.pic_height; /* Sanity check */ if( p_pict->p[0].i_pitch < i_width || p_pict->p[0].i_lines < i_height ) { msg_Err( p_enc, "frame is smaller than encoding size" "(%ix%i->%ix%i) -> dropping frame", p_pict->p[0].i_pitch, p_pict->p[0].i_lines, i_width, i_height ); return NULL; } /* Daala is a one-frame-in, one-frame-out system. Submit a frame * for compression and pull out the packet. */ img.nplanes = p_sys->di.nplanes; img.width = i_width; img.height = i_height; for( int i = 0; i < img.nplanes; i++ ) { img.planes[i].data = p_pict->p[i].p_pixels; img.planes[i].xdec = p_sys->di.plane_info[i].xdec; img.planes[i].ydec = p_sys->di.plane_info[i].ydec; img.planes[i].xstride = 1; img.planes[i].ystride = p_pict->p[i].i_pitch; } if( daala_encode_img_in( p_sys->dcx, &img, 0 ) < 0 ) { msg_Warn( p_enc, "failed encoding a frame" ); return NULL; } daala_encode_packet_out( p_sys->dcx, 0, &oggpacket ); /* Ogg packet to block */ p_block = block_Alloc( oggpacket.bytes ); memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes ); p_block->i_dts = p_block->i_pts = p_pict->date; if( daala_packet_iskeyframe( oggpacket.packet, oggpacket.bytes ) ) p_block->i_flags |= BLOCK_FLAG_TYPE_I; return p_block; }
/***************************************************************************** * DecodePacket: decodes a Daala packet. *****************************************************************************/ static picture_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; od_img ycbcr; if (daala_decode_packet_in( p_sys->dcx, &ycbcr, p_oggpacket ) < 0) return NULL; /* bad packet */ /* Check for keyframe */ if( daala_packet_iskeyframe( p_oggpacket->packet, p_oggpacket->bytes ) ) p_sys->b_decoded_first_keyframe = true; /* Get a new picture */ p_pic = decoder_NewPicture( p_dec ); if( !p_pic ) return NULL; daala_CopyPicture( p_pic, &ycbcr ); p_pic->date = p_sys->i_pts; return p_pic; }
static int open_encoder(struct videnc_state *ves, const struct vidsz *size) { daala_info di; daala_comment dc; daala_packet dp; int err = 0; int complexity = 7; int video_q = 30; int bitrate = ves->bitrate; info("daala: open encoder (%d x %d, %d bps)\n", size->w, size->h, bitrate); if (ves->enc) { debug("daala: re-opening encoder\n"); daala_encode_free(ves->enc); } daala_info_init(&di); daala_comment_init(&dc); di.pic_width = size->w; di.pic_height = size->h; di.timebase_numerator = 1; di.timebase_denominator = ves->fps; di.frame_duration = 1; di.pixel_aspect_numerator = -1; di.pixel_aspect_denominator = -1; di.nplanes = 3; di.plane_info[0].xdec = 0; /* YUV420P */ di.plane_info[0].ydec = 0; di.plane_info[1].xdec = 1; di.plane_info[1].ydec = 1; di.plane_info[2].xdec = 1; di.plane_info[2].ydec = 1; di.keyframe_rate = 100; info("daala: open encoder with bitstream version %u.%u.%u\n", di.version_major, di.version_minor, di.version_sub); ves->enc = daala_encode_create(&di); if (!ves->enc) { warning("daala: failed to open DAALA encoder\n"); return ENOMEM; } daala_encode_ctl(ves->enc, OD_SET_QUANT, &video_q, sizeof(video_q)); daala_encode_ctl(ves->enc, OD_SET_COMPLEXITY, &complexity, sizeof(complexity)); daala_encode_ctl(ves->enc, OD_SET_BITRATE, &bitrate, sizeof(bitrate)); for (;;) { int r; r = daala_encode_flush_header(ves->enc, &dc, &dp); if (r < 0) { warning("daala: flush_header returned %d\n", r); break; } else if (r == 0) break; debug("daala: header: %lld bytes header=%d key=%d\n", dp.bytes, daala_packet_isheader(&dp), daala_packet_iskeyframe(&dp)); #if 0 re_printf("bos=%lld, eos=%lld, granule=%lld, packetno=%lld\n", dp.b_o_s, dp.e_o_s, dp.granulepos, dp.packetno); #endif err = send_packet(ves, dp.b_o_s, dp.packet, dp.bytes); if (err) break; } daala_info_clear(&di); daala_comment_clear(&dc); return err; }