func: static int dvbsub_decode(AVCodecContext *avctx,
  
                           void *data, int *data_size,
  
                           AVPacket *avpkt)
  
  {
  
      const uint8_t *buf = avpkt->data;
  
      int buf_size = avpkt->size;
  
      DVBSubContext *ctx = avctx->priv_data;
  
      AVSubtitle *sub = data;
  
      const uint8_t *p, *p_end;
  
      int segment_type;
  
      int page_id;
  
      int segment_length;
  
      int i;
  
  
  
      av_dlog(avctx, "DVB sub packet:\n");
  
  
  
      for (i=0; i < buf_size; i++) {
  
          av_dlog(avctx, "%02x ", buf[i]);
  
          if (i % 16 == 15)
  
              av_dlog(avctx, "\n");
  
      }
  
  
  
      if (i % 16)
  
          av_dlog(avctx, "\n");
  
  
  
      if (buf_size <= 6 || *buf != 0x0f) {
  
          av_dlog(avctx, "incomplete or broken packet");
  
          return -1;
  
      }
  
  
  
      p = buf;
  
      p_end = buf + buf_size;
  
  
  
      while (p_end - p >= 6 && *p == 0x0f) {
  
          p += 1;
  
          segment_type = *p++;
  
          page_id = AV_RB16(p);
  
          p += 2;
  
          segment_length = AV_RB16(p);
  
          p += 2;
  
  
  
          if (p_end - p < segment_length) {
  
              av_dlog(avctx, "incomplete or broken packet");
  
              return -1;
  
          }
  
  
  
          if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
  
              ctx->composition_id == -1 || ctx->ancillary_id == -1) {
  
              switch (segment_type) {
  
              case DVBSUB_PAGE_SEGMENT:
  
                  dvbsub_parse_page_segment(avctx, p, segment_length);
  
                  break;
  
              case DVBSUB_REGION_SEGMENT:
  
                  dvbsub_parse_region_segment(avctx, p, segment_length);
  
                  break;
  
              case DVBSUB_CLUT_SEGMENT:
  
                  dvbsub_parse_clut_segment(avctx, p, segment_length);
  
                  break;
  
              case DVBSUB_OBJECT_SEGMENT:
  
                  dvbsub_parse_object_segment(avctx, p, segment_length);
  
                  break;
  
              case DVBSUB_DISPLAYDEFINITION_SEGMENT:
  
                  dvbsub_parse_display_definition_segment(avctx, p, segment_length);
  
                  break;
  
              case DVBSUB_DISPLAY_SEGMENT:
  
                  *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
  
                  break;
  
              default:
  
                  av_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n",
  
                          segment_type, page_id, segment_length);
  
                  break;
  
              }
  
          }
  
  
  
          p += segment_length;
  
      }
  
  
  
      return p - buf;
  
  }
  