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;
  }
}
Beispiel #2
0
/*****************************************************************************
 * 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;
}
Beispiel #3
0
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;
}