static GstFlowReturn daala_handle_type_packet (GstDaalaDec * dec) { gint par_num, par_den; GstFlowReturn ret = GST_FLOW_OK; GstVideoCodecState *state; GstVideoFormat fmt; GstVideoInfo *info; if (!dec->input_state) return GST_FLOW_NOT_NEGOTIATED; info = &dec->input_state->info; GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d", dec->info.timebase_numerator, dec->info.timebase_denominator, dec->info.pixel_aspect_numerator, dec->info.pixel_aspect_denominator); /* calculate par * the info.aspect_* values reflect PAR; * 0:x and x:0 are allowed and can be interpreted as 1:1. */ par_num = GST_VIDEO_INFO_PAR_N (info); par_den = GST_VIDEO_INFO_PAR_D (info); /* If we have a default PAR, see if the decoder specified a different one */ if (par_num == 1 && par_den == 1 && (dec->info.pixel_aspect_numerator != 0 && dec->info.pixel_aspect_denominator != 0)) { par_num = dec->info.pixel_aspect_numerator; par_den = dec->info.pixel_aspect_denominator; } /* daala has: * * width/height : dimension of the encoded frame * pic_width/pic_height : dimension of the visible part * pic_x/pic_y : offset in encoded frame where visible part starts */ GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.pic_width, dec->info.pic_height, par_num, par_den); if (dec->info.nplanes == 3 && dec->info.plane_info[0].xdec == 0 && dec->info.plane_info[0].ydec == 0 && dec->info.plane_info[1].xdec == 1 && dec->info.plane_info[1].ydec == 1 && dec->info.plane_info[2].xdec == 1 && dec->info.plane_info[2].ydec == 1) { fmt = GST_VIDEO_FORMAT_I420; } else if (dec->info.nplanes == 3 && dec->info.plane_info[0].xdec == 0 && dec->info.plane_info[0].ydec == 0 && dec->info.plane_info[1].xdec == 0 && dec->info.plane_info[1].ydec == 0 && dec->info.plane_info[2].xdec == 0 && dec->info.plane_info[2].ydec == 0) { fmt = GST_VIDEO_FORMAT_Y444; } else { goto unsupported_format; } GST_VIDEO_INFO_WIDTH (info) = dec->info.pic_width; GST_VIDEO_INFO_HEIGHT (info) = dec->info.pic_height; /* done */ dec->decoder = daala_decode_alloc (&dec->info, dec->setup); /* Create the output state */ dec->output_state = state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), fmt, info->width, info->height, dec->input_state); /* FIXME : Do we still need to set fps/par now that we pass the reference input stream ? */ state->info.fps_n = dec->info.timebase_numerator; state->info.fps_d = dec->info.timebase_denominator; state->info.par_n = par_num; state->info.par_d = par_den; gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec)); dec->have_header = TRUE; return ret; /* ERRORS */ unsupported_format: { GST_ERROR_OBJECT (dec, "Invalid pixel format"); return GST_FLOW_ERROR; } }
/***************************************************************************** * ProcessHeaders: process Daala headers. *****************************************************************************/ static int ProcessHeaders( decoder_t *p_dec ) { int ret = VLC_SUCCESS; decoder_sys_t *p_sys = p_dec->p_sys; ogg_packet oggpacket; daala_setup_info *ds = NULL; /* daala setup information */ unsigned pi_size[XIPH_MAX_HEADER_COUNT]; void *pp_data[XIPH_MAX_HEADER_COUNT]; unsigned i_count; if( xiph_SplitHeaders( pi_size, pp_data, &i_count, p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) ) return VLC_EGENERIC; if( i_count < 3 ) return VLC_EGENERIC; oggpacket.granulepos = -1; oggpacket.e_o_s = 0; oggpacket.packetno = 0; /* Take care of the initial info header */ oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */ oggpacket.bytes = pi_size[0]; oggpacket.packet = pp_data[0]; if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &oggpacket ) < 0 ) { msg_Err( p_dec, "this bitstream does not contain Daala video data" ); ret = VLC_EGENERIC; goto cleanup; } /* Set output properties */ if( !p_sys->b_packetizer ) { if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 && p_sys->di.plane_info[1].xdec == 1 && p_sys->di.plane_info[1].ydec == 1 && p_sys->di.plane_info[2].xdec == 1 && p_sys->di.plane_info[2].ydec == 1 ) { p_dec->fmt_out.i_codec = VLC_CODEC_I420; } else if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 && p_sys->di.plane_info[1].xdec == 0 && p_sys->di.plane_info[1].ydec == 0 && p_sys->di.plane_info[2].xdec == 0 && p_sys->di.plane_info[2].ydec == 0 ) { p_dec->fmt_out.i_codec = VLC_CODEC_I444; } else { msg_Err( p_dec, "unknown chroma in daala sample" ); } } p_dec->fmt_out.video.i_width = p_sys->di.pic_width; p_dec->fmt_out.video.i_height = p_sys->di.pic_height; if( p_sys->di.pic_width && p_sys->di.pic_height ) { p_dec->fmt_out.video.i_visible_width = p_sys->di.pic_width; p_dec->fmt_out.video.i_visible_height = p_sys->di.pic_height; } if( p_sys->di.pixel_aspect_denominator && p_sys->di.pixel_aspect_numerator ) { p_dec->fmt_out.video.i_sar_num = p_sys->di.pixel_aspect_numerator; p_dec->fmt_out.video.i_sar_den = p_sys->di.pixel_aspect_denominator; } else { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } if( p_sys->di.timebase_numerator > 0 && p_sys->di.timebase_denominator > 0 ) { p_dec->fmt_out.video.i_frame_rate = p_sys->di.timebase_numerator; p_dec->fmt_out.video.i_frame_rate_base = p_sys->di.timebase_denominator; } msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content ", p_sys->di.pic_width, p_sys->di.pic_height, (double)p_sys->di.timebase_numerator/p_sys->di.timebase_denominator ); /* The next packet in order is the comments header */ oggpacket.b_o_s = 0; oggpacket.bytes = pi_size[1]; oggpacket.packet = pp_data[1]; if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &oggpacket ) < 0 ) { msg_Err( p_dec, "Daala comment header is corrupted" ); ret = VLC_EGENERIC; goto cleanup; } ParseDaalaComments( p_dec ); /* The next packet in order is the setup header * We need to watch out that this packet is not missing as a * missing or corrupted header is fatal. */ oggpacket.b_o_s = 0; oggpacket.bytes = pi_size[2]; oggpacket.packet = pp_data[2]; if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &oggpacket ) < 0 ) { msg_Err( p_dec, "Daala setup header is corrupted" ); ret = VLC_EGENERIC; goto cleanup; } if( !p_sys->b_packetizer ) { /* We have all the headers, initialize decoder */ if ( ( p_sys->dcx = daala_decode_alloc( &p_sys->di, ds ) ) == NULL ) { msg_Err( p_dec, "Could not allocate Daala decoder" ); ret = VLC_EGENERIC; goto cleanup; } } else { p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra ); } cleanup: /* Clean up the decoder setup info... we're done with it */ daala_setup_free( ds ); return ret; }
int player_example_play(player_example *player) { size_t bytes; char *buffer; int ret; ogg_page page; ogg_packet packet; daala_setup_info *dsi; dsi = NULL; while (!player->done) { while (ogg_sync_pageout(&player->oy, &page) != 1) { buffer = ogg_sync_buffer(&player->oy, 4096); if (buffer == NULL) return -1; bytes = fread(buffer, 1, 4096, player->input); if (bytes > 0) { ret = ogg_sync_wrote(&player->oy, bytes); if (ret != 0) return -1; } else { if (!player->valid) { fprintf(stderr, "Invalid Ogg\n"); exit(1); } if (player->od_state != ODS_NONE) { ret = player_example_daala_stream_clear(player); if (ret != 0) return -1; } if (player->input == stdin) { return 0; } if (player->loop == 1) { player_example_input_restart(player); continue; } for (;;) { player_example_wait_user_input(player); if (player->restart) { ret = player_example_input_restart(player); player->restart = 0; if (ret != 0) return -1; break; } if (player->done) { return 0; } } } } if (ogg_page_bos(&page)) { ret = player_example_daala_stream_init(player, ogg_page_serialno(&page)); if (ret != 0) return -1; } ret = ogg_stream_pagein(&player->os, &page); if (ret != 0) return -1; while (ogg_stream_packetout(&player->os, &packet) == 1) { switch (player->od_state) { case ODS_HEADER: { ret = daala_decode_header_in(&player->di, &player->dc, &dsi, &packet); if (ret < 0) { if (memcmp(packet.packet, "fishead", packet.bytes)) { fprintf(stderr, "Ogg Skeleton streams not supported\n"); } return -1; } if (ret != 0) break; player->dctx = daala_decode_alloc(&player->di, dsi); if (player->dctx == NULL) return -1; daala_setup_free(dsi); dsi = NULL; player->od_state = ODS_DATA; /* Falling through */ } case ODS_DATA: { if ((player->screen == NULL) || (player->width != player->di.pic_width) || (player->height != player->di.pic_height)) { player->width = player->di.pic_width; player->height = player->di.pic_height; player->screen = SDL_SetVideoMode(player->width, player->height, 24, SDL_HWSURFACE | SDL_DOUBLEBUF); if (player->screen == NULL) return -1; player->surf = SDL_GetVideoSurface(); if (player->surf == NULL) return -1; } ret = daala_decode_packet_in(player->dctx, &player->img, &packet); if (ret != 0) return -1; player->valid = 1; if ((player->slow) && (!player->step)) { SDL_Delay(420); } player_example_check_user_input(player); while ((player->paused) && (!player->done)) { if (player->restart) { break; } if (player->step) { player->step = 0; break; } player_example_wait_user_input(player); } if ((!player->restart) && (!player->done)) { SDL_LockSurface(player->surf); img_to_rgb(player->surf, &player->img); SDL_UnlockSurface(player->surf); SDL_Flip(player->screen); } break; } } } if ((player->restart) || (ogg_page_eos(&page))) { ret = player_example_daala_stream_clear(player); if (ret != 0) return -1; } if (player->restart) { ret = player_example_input_restart(player); player->restart = 0; if (ret != 0) return -1; } } if (player->od_state != ODS_NONE) { ret = player_example_daala_stream_clear(player); if (ret != 0) return -1; } return 0; }