Exemplo n.º 1
0
static gboolean
gst_x265_enc_set_level_tier_and_profile (GstX265Enc * encoder, GstCaps * caps)
{
  x265_nal *nal, *vps_nal;
  guint32 i_nal;
  int header_return;

  GST_DEBUG_OBJECT (encoder, "set profile, level and tier");

  header_return = x265_encoder_headers (encoder->x265enc, &nal, &i_nal);
  if (header_return < 0) {
    GST_ELEMENT_ERROR (encoder, STREAM, ENCODE, ("Encode x265 header failed."),
        ("x265_encoder_headers return code=%d", header_return));
    return FALSE;
  }

  GST_DEBUG_OBJECT (encoder, "%d nal units in header", i_nal);

  g_assert (nal[0].type == NAL_UNIT_VPS);
  vps_nal = gst_x265_enc_bytestream_to_nal (&nal[0]);

  GST_MEMDUMP ("VPS", vps_nal->payload, vps_nal->sizeBytes);

  if (!gst_codec_utils_h265_caps_set_level_tier_and_profile (caps,
          vps_nal->payload + 6, vps_nal->sizeBytes - 6)) {
    GST_ELEMENT_ERROR (encoder, STREAM, ENCODE, ("Encode x265 failed."),
        ("Failed to find correct level, tier or profile in VPS"));
    return FALSE;
  }

  x265_nal_free (vps_nal);

  return TRUE;
}
Exemplo n.º 2
0
/**
 * gst_codec_utils_h265_get_profile:
 * @profile_tier_level: Pointer to the profile_tier_level
 *   structure for the stream.
 * @len: Length of the data available in @profile_tier_level
 *
 * Converts the profile indication (general_profile_idc) in the stream's
 * profile_level_tier structure into a string. The profile_tier_level is
 * expected to have the following format, as defined in the H.265
 * specification. The profile_tier_level is viewed as a bitstream here,
 * with bit 0 being the most significant bit of the first byte.
 *
 * <itemizedlist>
 * <listitem><para>Bit 0:1   - general_profile_space</para></listitem>
 * <listitem><para>Bit 2     - general_tier_flag</para></listitem>
 * <listitem><para>Bit 3:7   - general_profile_idc</para></listitem>
 * <listitem><para>Bit 8:39  - gernal_profile_compatibility_flags</para></listitem>
 * <listitem><para>Bit 40    - general_progressive_source_flag</para></listitem>
 * <listitem><para>Bit 41    - general_interlaced_source_flag</para></listitem>
 * <listitem><para>Bit 42    - general_non_packed_constraint_flag</para></listitem>
 * <listitem><para>Bit 43    - general_frame_only_constraint_flag</para></listitem>
 * <listitem><para>Bit 44:87 - general_reserved_zero_44bits</para></listitem>
 * <listitem><para>Bit 88:95 - general_level_idc</para></listitem>
 * </itemizedlist>
 *
 * Returns: The profile as a const string, or %NULL if there is an error.
 *
 * Since 1.4
 */
const gchar *
gst_codec_utils_h265_get_profile (const guint8 * profile_tier_level, guint len)
{
  const gchar *profile = NULL;
  gint gpcf1 = 0, gpcf2 = 0, gpcf3 = 0;
  gint profile_idc;

  g_return_val_if_fail (profile_tier_level != NULL, NULL);

  if (len < 2)
    return NULL;

  GST_MEMDUMP ("ProfileTierLevel", profile_tier_level, len);

  profile_idc = (profile_tier_level[0] & 0x1f);

  gpcf1 = (profile_tier_level[1] & 0x40) >> 6;
  gpcf2 = (profile_tier_level[1] & 0x20) >> 5;
  gpcf3 = (profile_tier_level[1] & 0x10) >> 4;

  if (profile_idc == 1 || gpcf1)
    profile = "main";
  else if (profile_idc == 2 || gpcf2)
    profile = "main-10";
  else if (profile_idc == 3 || gpcf3)
    profile = "main-still-picture";
  else
    profile = NULL;

  return profile;
}
Exemplo n.º 3
0
static void
rtp_jpeg_do_packet_loss (gdouble prob, gint num_expected)
{
  GstHarness *h;
  gboolean eos = FALSE;
  gchar *s;
  guint i, buffer_count;

  s = g_strdup_printf ("videotestsrc pattern=ball num-buffers=100 ! "
      "jpegenc quality=50 ! rtpjpegpay ! identity drop-probability=%g ! "
      "rtpjpegdepay", prob);
  GST_INFO ("running pipeline %s", s);
  h = gst_harness_new_parse (s);
  g_free (s);

  gst_harness_play (h);

  do {
    GstEvent *event;

    event = gst_harness_pull_event (h);
    eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
    gst_event_unref (event);
  } while (!eos);

  buffer_count = gst_harness_buffers_received (h);
  GST_INFO ("Got %u buffers", buffer_count);

  if (num_expected >= 0) {
    fail_unless_equals_int (num_expected, buffer_count);
  }

  for (i = 0; i < buffer_count; ++i) {
    GstBuffer *buf;
    GstMapInfo map;
    guint16 soi, eoi;

    buf = gst_harness_pull (h);
    fail_unless (buf != NULL);

    fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
    GST_MEMDUMP ("jpeg frame", map.data, map.size);
    fail_unless (map.size > 4);
    soi = GST_READ_UINT16_BE (map.data);
    fail_unless (soi == 0xffd8, "expected JPEG frame start FFD8 not %02X", soi);
    eoi = GST_READ_UINT16_BE (map.data + map.size - 2);
    fail_unless (eoi == 0xffd9, "expected JPEG frame end FFD9 not %02X", eoi);
    gst_buffer_unmap (buf, &map);
    gst_buffer_unref (buf);
  }

  gst_harness_teardown (h);
}
Exemplo n.º 4
0
static void
check_buffer_equal (GstBuffer * buf, GstBuffer * expected)
{
  GstMapInfo info_buf, info_expected;

  fail_if (buf == NULL);
  fail_if (expected == NULL);

  fail_unless (gst_buffer_map (buf, &info_buf, GST_MAP_READ));
  fail_unless (gst_buffer_map (expected, &info_expected, GST_MAP_READ));

  GST_LOG ("buffer: size %" G_GSIZE_FORMAT, info_buf.size);
  GST_LOG ("expected: size %" G_GSIZE_FORMAT, info_expected.size);
  GST_MEMDUMP ("buffer", info_buf.data, info_buf.size);
  GST_MEMDUMP ("expected", info_expected.data, info_expected.size);

  fail_unless_equals_uint64 (info_buf.size, info_expected.size);
  fail_unless_equals_int (memcmp (info_buf.data, info_expected.data,
          info_buf.size), 0);

  gst_buffer_unmap (buf, &info_buf);
  gst_buffer_unmap (expected, &info_expected);
}
Exemplo n.º 5
0
static void
convert_line_uyvy (GstVideoVBIParser * parser, const guint8 * data)
{
  guint i;
  guint8 *y = parser->work_data;
  guint8 *uv = y + parser->info.width;

  for (i = 0; i < parser->info.width - 3; i += 4) {
    *uv++ = data[(i / 4) * 4 + 0];
    *y++ = data[(i / 4) * 4 + 1];
    *uv++ = data[(i / 4) * 4 + 2];
    *y++ = data[(i / 4) * 4 + 3];
  }
  GST_MEMDUMP ("Converted line", parser->work_data, 128);
}
Exemplo n.º 6
0
static GstFlowReturn
gst_jif_mux_chain (GstPad * pad, GstBuffer * buf)
{
    GstJifMux *self = GST_JIF_MUX (GST_PAD_PARENT (pad));
    GstFlowReturn fret = GST_FLOW_OK;

    if (GST_BUFFER_CAPS (buf) == NULL) {
        GST_WARNING_OBJECT (self, "Rejecting buffer without caps");
        gst_buffer_unref (buf);
        return GST_FLOW_NOT_NEGOTIATED;
    }

    GST_MEMDUMP ("jpeg beg", GST_BUFFER_DATA (buf), 64);
    GST_MEMDUMP ("jpeg end", GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf) - 64,
                 64);

    /* we should have received a whole picture from SOI to EOI
     * build a list of markers */
    if (gst_jif_mux_parse_image (self, buf)) {
        /* modify marker list */
        if (gst_jif_mux_mangle_markers (self)) {
            /* the list was changed, remux */
            GstBuffer *old = buf;
            fret = gst_jif_mux_recombine_image (self, &buf, old);
            gst_buffer_unref (old);
        }
    }

    /* free the marker list */
    gst_jif_mux_reset (self);

    if (fret == GST_FLOW_OK) {
        fret = gst_pad_push (self->priv->srcpad, buf);
    }
    return fret;
}
//
// Expected synchronisation from caller. This method is not thread-safe!
//
bool PlayreadySession::playreadyProcessKey(Uint8Array* key, RefPtr<Uint8Array>& nextMessage, unsigned short& errorCode, uint32_t& systemCode)
{
    DRM_RESULT dr = DRM_SUCCESS;
    DRM_LICENSE_RESPONSE oLicenseResponse = {eUnknownProtocol, 0};
    uint8_t *m_pbKeyMessageResponse = key->data();
    uint32_t m_cbKeyMessageResponse = key->byteLength();

    GST_MEMDUMP("response received :", key->data(), key->byteLength());

    // The current state MUST be KEY_PENDING otherwise error out.
    ChkBOOL(m_eKeyState == KEY_PENDING, DRM_E_INVALIDARG);

    ChkArg(m_pbKeyMessageResponse != NULL && m_cbKeyMessageResponse > 0);

    ChkDR(Drm_LicenseAcq_ProcessResponse(m_poAppContext,
                                         DRM_PROCESS_LIC_RESPONSE_SIGNATURE_NOT_REQUIRED,
                                         NULL,
                                         NULL,
                                         const_cast<DRM_BYTE *>(m_pbKeyMessageResponse),
                                         m_cbKeyMessageResponse,
                                         &oLicenseResponse));

    ChkDR(Drm_Reader_Bind(m_poAppContext,
                          g_rgpdstrRights,
                          NO_OF(g_rgpdstrRights),
                          _PolicyCallback,
                          NULL,
                          &m_oDecryptContext));

    m_key = key->buffer();
    errorCode = 0;
    m_eKeyState = KEY_READY;
    GST_DEBUG("key processed, now ready for content decryption");
    systemCode = dr;
    return true;

ErrorExit:
    if (DRM_FAILED(dr)) {
        GST_ERROR("failed processing license response");
        errorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
        m_eKeyState = KEY_ERROR;
    }
    return false;
}
static GstCaps *
typefind_data (const guint8 * data, gsize data_size,
    GstTypeFindProbability * prob)
{
  GstBuffer *buf;
  GstCaps *caps;

  GST_MEMDUMP ("typefind data", data, data_size);
  buf = gst_buffer_new ();
  gst_buffer_append_memory (buf,
      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
          (guint8 *) data, data_size, 0, data_size, NULL, NULL));
  GST_BUFFER_OFFSET (buf) = 0;

  caps = gst_type_find_helper_for_buffer (NULL, buf, prob);
  GST_INFO ("caps: %" GST_PTR_FORMAT ", probability=%u", caps, *prob);

  gst_buffer_unref (buf);

  return caps;
}
Exemplo n.º 9
0
/**
 * gst_codec_utils_h265_get_level:
 * @profile_tier_level: Pointer to the profile_tier_level structure
 *   for the stream
 * @len: Length of the data available in @profile_tier_level.
 *
 * Converts the level indication (general_level_idc) in the stream's
 * profile_tier_level structure into a string. The profiel_tier_level is
 * expected to have the same format as for gst_codec_utils_h264_get_profile().
 *
 * Returns: The level as a const string, or %NULL if there is an error.
 *
 * Since 1.4
 */
const gchar *
gst_codec_utils_h265_get_level (const guint8 * profile_tier_level, guint len)
{
  g_return_val_if_fail (profile_tier_level != NULL, NULL);

  if (len < 12)
    return NULL;

  GST_MEMDUMP ("ProfileTierLevel", profile_tier_level, len);

  if (profile_tier_level[11] % 30 == 0)
    return digit_to_string (profile_tier_level[11] / 30);
  else {
    switch (profile_tier_level[11]) {
      case 63:
        return "2.1";
        break;
      case 93:
        return "3.1";
        break;
      case 123:
        return "4.1";
        break;
      case 153:
        return "5.1";
        break;
      case 156:
        return "5.2";
        break;
      case 183:
        return "6.1";
        break;
      case 186:
        return "6.2";
        break;
      default:
        return NULL;
    }
  }
}
Exemplo n.º 10
0
//
// Expected synchronisation from caller. This method is not thread-safe!
//
PassRefPtr<Uint8Array> DiscretixSession::dxdrmGenerateKeyRequest(Uint8Array* initData, String& destinationURL, unsigned short& errorCode, unsigned long& systemCode)
{
    RefPtr<Uint8Array> result;

    EDxDrmStatus status = DxDrmClient_OpenDrmStreamFromData(&m_DxDrmStream, initData->data(), initData->byteLength());

    GST_DEBUG("generating key request");
    m_keyRequested = true;
    if (status != DX_SUCCESS) {
        GST_ERROR("failed to create DxDrmClient from initData (status: %d)", status);
        reportError(status);
        errorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
    } else {
        uint32_t challengeLength = MAX_CHALLENGE_LEN;
        unsigned char* challenge = static_cast<unsigned char*>(g_malloc0(challengeLength));

        // Get challenge
        status = DxDrmStream_GetLicenseChallenge(m_DxDrmStream, challenge, &challengeLength);
        if (status != DX_SUCCESS) {
            GST_ERROR("failed to generate challenge request (status: %d)", status);
            errorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
        } else {
            // Get License URL
            destinationURL = static_cast<const char *>(DxDrmStream_GetTextAttribute(m_DxDrmStream, DX_ATTR_SILENT_URL, DX_ACTIVE_CONTENT));
            GST_DEBUG("destination URL : %s", destinationURL.utf8().data());

            GST_MEMDUMP("generated license request :", challenge, challengeLength);

            result = Uint8Array::create(challenge, challengeLength);
            errorCode = 0;
        }

        g_free(challenge);
    }

    systemCode = status;

    return result;
}
Exemplo n.º 11
0
/**
 * gst_codec_utils_h265_get_tier:
 * @profile_tier_level: Pointer to the profile_tier_level structure
 *   for the stream.
 * @len: Length of the data available in @profile_tier_level.
 *
 * Converts the tier indication (general_tier_flag) in the stream's
 * profile_tier_level structure into a string. The profile_tier_level
 * is expected to have the same format as for gst_codec_utils_h264_get_profile().
 *
 * Returns: The tier as a const string, or %NULL if there is an error.
 *
 * Since 1.4
 */
const gchar *
gst_codec_utils_h265_get_tier (const guint8 * profile_tier_level, guint len)
{
  const gchar *tier = NULL;
  gint tier_flag = 0;

  g_return_val_if_fail (profile_tier_level != NULL, NULL);

  if (len < 1)
    return NULL;

  GST_MEMDUMP ("ProfileTierLevel", profile_tier_level, len);

  tier_flag = (profile_tier_level[0] & 0x20) >> 5;

  if (tier_flag)
    tier = "high";
  else
    tier = "main";

  return tier;
}
Exemplo n.º 12
0
static void
btic_midi_device_constructed (GObject * object)
{
  const BtIcMidiDevice *const self = BTIC_MIDI_DEVICE (object);

  if (G_OBJECT_CLASS (btic_midi_device_parent_class)->constructed)
    G_OBJECT_CLASS (btic_midi_device_parent_class)->constructed (object);

  btic_learn_load_controller_map (BTIC_LEARN (self));

#if 0
  // also see design/midi/rawmidi.c
  gint io;
  if ((io = open (self->priv->devnode, O_NONBLOCK | O_RDWR | O_SYNC)) > 0) {
    gchar data[17] = { 0, };
    gsize ct;

    data[0] = MIDI_SYS_EX_START;
    data[1] = MIDI_NON_REALTIME;
    data[2] = 0x7f;             // SysEx channel, set to "disregard"
    data[3] = 0x06;             // General Information
    data[4] = 0x01;             // Identity Request
    data[5] = MIDI_SYS_EX_END;
    GST_INFO ("send identity request to: %s", self->priv->devnode);
    if ((ct = write (io, data, 6)) < 6)
      goto done;
    do {
      ct = read (io, data, 15);
    } while (ct == -1);
    GST_MEMDUMP ("reply", (guint8 *) data, 15);
    // 5:   manufacturer id (if 0, then id is next two bytes)
    // 6,7: family code
    // 8,9: model code
    // 10,11,12,13: version number
  done:
    close (io);
  }
#endif
}
Exemplo n.º 13
0
static guint
gst_mpeg_descriptor_parse_1 (guint8 * data, guint size)
{
  guint8 tag;
  guint8 length;

  /* need at least 2 bytes for tag and length */
  if (size < 2)
    return 0;

  tag = *data++;
  length = *data++;
  size -= 2;

  GST_DEBUG ("tag: 0x%02x, length: %d", tag, length);

  if (length > size)
    return 0;

  GST_MEMDUMP ("tag contents:", data, length);

  return length + 2;
}
static gpointer
_parse_atsc_vct (GstMpegtsSection * section)
{
    GstMpegtsAtscVCT *vct = NULL;
    guint8 *data, *end, source_nb;
    guint32 tmp32;
    guint16 descriptors_loop_length, tmp16;
    guint i;
    GError *err = NULL;

    vct = g_slice_new0 (GstMpegtsAtscVCT);

    data = section->data;
    end = data + section->section_length;

    vct->transport_stream_id = section->subtable_extension;

    /* Skip already parsed data */
    data += 8;

    /* minimum size */
    if (end - data < 2 + 2 + 4)
        goto error;

    vct->protocol_version = *data;
    data += 1;

    source_nb = *data;
    data += 1;

    vct->sources = g_ptr_array_new_full (source_nb,
                                         (GDestroyNotify) _gst_mpegts_atsc_vct_source_free);

    for (i = 0; i < source_nb; i++) {
        GstMpegtsAtscVCTSource *source;

        /* minimum 32 bytes for a entry, 2 bytes second descriptor
           loop-length, 4 bytes crc */
        if (end - data < 32 + 2 + 4)
            goto error;

        source = g_slice_new0 (GstMpegtsAtscVCTSource);
        g_ptr_array_add (vct->sources, source);

        source->short_name =
            g_convert ((gchar *) data, 14, "utf-8", "utf-16be", NULL, NULL, &err);
        if (err) {
            GST_WARNING ("Failed to convert VCT Source short_name to utf-8: %d %s",
                         err->code, err->message);
            GST_MEMDUMP ("UTF-16 string", data, 14);
            g_error_free (err);
        }
        data += 14;

        tmp32 = GST_READ_UINT32_BE (data);
        source->major_channel_number = (tmp32 >> 18) & 0x03FF;
        source->minor_channel_number = (tmp32 >> 8) & 0x03FF;
        source->modulation_mode = tmp32 & 0xF;
        data += 4;

        source->carrier_frequency = GST_READ_UINT32_BE (data);
        data += 4;

        source->channel_TSID = GST_READ_UINT16_BE (data);
        data += 2;

        source->program_number = GST_READ_UINT16_BE (data);
        data += 2;

        tmp16 = GST_READ_UINT16_BE (data);
        source->ETM_location = (tmp16 >> 14) & 0x3;
        source->access_controlled = (tmp16 >> 13) & 0x1;
        source->hidden = (tmp16 >> 12) & 0x1;

        /* only used in CVCT */
        source->path_select = (tmp16 >> 11) & 0x1;
        source->out_of_band = (tmp16 >> 10) & 0x1;

        source->hide_guide = (tmp16 >> 9) & 0x1;
        source->service_type = tmp16 & 0x3f;
        data += 2;

        source->source_id = GST_READ_UINT16_BE (data);
        data += 2;

        descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x03FF;
        data += 2;

        if (end - data < descriptors_loop_length + 6)
            goto error;

        source->descriptors =
            gst_mpegts_parse_descriptors (data, descriptors_loop_length);
        if (source->descriptors == NULL)
            goto error;
        data += descriptors_loop_length;
    }

    descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x03FF;
    data += 2;

    if (end - data < descriptors_loop_length + 4)
        goto error;

    vct->descriptors =
        gst_mpegts_parse_descriptors (data, descriptors_loop_length);
    if (vct->descriptors == NULL)
        goto error;
    data += descriptors_loop_length;

    return (gpointer) vct;

error:
    _gst_mpegts_atsc_vct_free (vct);

    return NULL;
}
Exemplo n.º 15
0
//
// Expected synchronisation from caller. This method is not thread-safe!
//
RefPtr<Uint8Array> PlayreadySession::playreadyGenerateKeyRequest(Uint8Array* initData, String& destinationURL, unsigned short& errorCode, uint32_t& systemCode)
{
    RefPtr<Uint8Array> result;
    DRM_RESULT dr = DRM_SUCCESS;
    DRM_BYTE *pbChallenge = NULL;
    DRM_DWORD cbChallenge = 0;
    DRM_CHAR *pchSilentURL = NULL;
    DRM_DWORD cchSilentURL = 0;
    DRM_ANSI_STRING dastrCustomData = EMPTY_DRM_STRING;

    GST_DEBUG("generating key request");
    GST_MEMDUMP("init data", initData->data(), initData->byteLength());

    // The current state MUST be KEY_INIT otherwise error out.
    ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG);

    ChkDR(Drm_Content_SetProperty(m_poAppContext,
                                  DRM_CSP_AUTODETECT_HEADER,
                                  initData->data(),
                                  initData->byteLength()));
    GST_DEBUG("init data set on DRM context");

    if (DRM_SUCCEEDED(Drm_Reader_Bind(m_poAppContext, g_rgpdstrRights, NO_OF(g_rgpdstrRights), _PolicyCallback, NULL, &m_oDecryptContext))) {
        GST_DEBUG("Play rights already acquired!");
        m_eKeyState = KEY_READY;
        systemCode = dr;
        errorCode = 0;
        return nullptr;
    }
    GST_DEBUG("DRM reader bound");

    // Try to figure out the size of the license acquisition
    // challenge to be returned.
    dr = Drm_LicenseAcq_GenerateChallenge(m_poAppContext,
                                          g_rgpdstrRights,
                                          NO_OF(g_rgpdstrRights),
                                          NULL,
                                          dastrCustomData.pszString, //m_pchCustomData,
                                          dastrCustomData.cchString, //m_cchCustomData,
                                          NULL,
                                          &cchSilentURL,
                                          NULL,
                                          NULL,
                                          pbChallenge,
                                          &cbChallenge);
 
    if (dr == DRM_E_BUFFERTOOSMALL) {
        if (cchSilentURL > 0) {
            ChkMem(pchSilentURL = (DRM_CHAR *)Oem_MemAlloc(cchSilentURL + 1));
            ZEROMEM(pchSilentURL, cchSilentURL + 1);
        }

        // Allocate buffer that is sufficient to store the license acquisition
        // challenge.
        if (cbChallenge > 0)
            ChkMem(pbChallenge = (DRM_BYTE *)Oem_MemAlloc(cbChallenge));

        dr = DRM_SUCCESS;
    } else {
         ChkDR(dr);
         GST_DEBUG("challenge generated");
    }

    // Supply a buffer to receive the license acquisition challenge.
    ChkDR(Drm_LicenseAcq_GenerateChallenge(m_poAppContext,
                                           g_rgpdstrRights,
                                           NO_OF(g_rgpdstrRights),
                                           NULL,
                                           NULL,
                                           0,
                                           pchSilentURL,
                                           &cchSilentURL,
                                           NULL,
                                           NULL,
                                           pbChallenge,
                                           &cbChallenge));

    GST_MEMDUMP("generated license request :", pbChallenge, cbChallenge);

    result = Uint8Array::create(pbChallenge, cbChallenge);
    destinationURL = static_cast<const char *>(pchSilentURL);
    GST_DEBUG("destination URL : %s", destinationURL.utf8().data());

    m_eKeyState = KEY_PENDING;
    systemCode = dr;
    errorCode = 0;
    SAFE_OEM_FREE(pbChallenge);
    SAFE_OEM_FREE(pchSilentURL);

    return result;

ErrorExit:
    if (DRM_FAILED(dr)) {
        GST_DEBUG("DRM key generation failed");
        errorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
    }
    return result;
}
Exemplo n.º 16
0
/**
 * validate_data:
 * @data: the data to validate
 * @len: the length of @data to validate
 * @payload: the payload if @data represents the header only
 * @payload_len: the len of the payload
 *
 * Checks if @data is a valid RTP packet.
 *
 * Returns: TRUE if @data is a valid RTP packet
 */
static gboolean
validate_data (guint8 * data, guint len, guint8 * payload, guint payload_len)
{
  guint8 padding;
  guint8 csrc_count;
  guint header_len;
  guint8 version;

  g_return_val_if_fail (data != NULL, FALSE);

  header_len = GST_RTP_HEADER_LEN;
  if (G_UNLIKELY (len < header_len))
    goto wrong_length;

  /* check version */
  version = (data[0] & 0xc0);
  if (G_UNLIKELY (version != (GST_RTP_VERSION << 6)))
    goto wrong_version;

  /* calc header length with csrc */
  csrc_count = (data[0] & 0x0f);
  header_len += csrc_count * sizeof (guint32);

  /* calc extension length when present. */
  if (data[0] & 0x10) {
    guint8 *extpos;
    guint16 extlen;

    /* this points to the extenstion bits and header length */
    extpos = &data[header_len];

    /* skip the header and check that we have enough space */
    header_len += 4;
    if (G_UNLIKELY (len < header_len))
      goto wrong_length;

    /* skip id */
    extpos += 2;
    /* read length as the number of 32 bits words */
    extlen = GST_READ_UINT16_BE (extpos);

    header_len += extlen * sizeof (guint32);
  }

  /* check for padding */
  if (data[0] & 0x20) {
    if (payload)
      padding = payload[payload_len - 1];
    else
      padding = data[len - 1];
  } else {
    padding = 0;
  }

  /* check if padding and header not bigger than packet length */
  if (G_UNLIKELY (len < padding + header_len))
    goto wrong_padding;

  return TRUE;

  /* ERRORS */
wrong_length:
  {
    GST_DEBUG ("len < header_len check failed (%d < %d)", len, header_len);
    goto dump_packet;
  }
wrong_version:
  {
    GST_DEBUG ("version check failed (%d != %d)", version, GST_RTP_VERSION);
    goto dump_packet;
  }
wrong_padding:
  {
    GST_DEBUG ("padding check failed (%d - %d < %d)", len, header_len, padding);
    goto dump_packet;
  }
dump_packet:
  {
    GST_MEMDUMP ("buffer", data, len);
    return FALSE;
  }
}
Exemplo n.º 17
0
//
// Expected synchronisation from caller. This method is not thread-safe!
//
bool DiscretixSession::dxdrmProcessKey(Uint8Array* key, RefPtr<Uint8Array>& nextMessage, unsigned short& errorCode, unsigned long& systemCode)
{
    GST_MEMDUMP("response received :", key->data(), key->byteLength());

    bool isAckRequired;
    HDxResponseResult responseResult = nullptr;
    EDxDrmStatus status = DX_ERROR_CONTENT_NOT_RECOGNIZED;

    errorCode = 0;
    if (m_state == PHASE_INITIAL) {
        // Server replied to our license request
        status = DxDrmStream_ProcessLicenseResponse(m_DxDrmStream, key->data(), key->byteLength(), &responseResult, &isAckRequired);

        if (status == DX_SUCCESS) {
            // Create a deep copy of the key.
            m_key = key->buffer();
            m_state = (isAckRequired ? PHASE_ACKNOWLEDGE : PHASE_PROVISIONED);
            GST_DEBUG("Acknowledgement required: %s", isAckRequired ? "yes" : "no");
        }

    } else if (m_state == PHASE_ACKNOWLEDGE) {

        // Server replied to our license response acknowledge
        status = DxDrmClient_ProcessServerResponse(key->data(), key->byteLength(), DX_RESPONSE_LICENSE_ACK, &responseResult, &isAckRequired);

        if (status == DX_SUCCESS) {
            // Create a deep copy of the key.
            m_key = key->buffer();
            m_state = (isAckRequired ? PHASE_ACKNOWLEDGE : PHASE_PROVISIONED);

            if (m_state == PHASE_ACKNOWLEDGE)
                GST_WARNING("Acknowledging an Ack. Strange situation.");
        }
    } else
        GST_WARNING("Unexpected call. We are already provisioned");

    if (status != DX_SUCCESS) {
        GST_ERROR("failed processing license response (status: %d)", status);
        errorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
    } else if (m_state == PHASE_PROVISIONED) {
        status = DxDrmStream_SetIntent(m_DxDrmStream, DX_INTENT_AUTO_PLAY, DX_AUTO_NO_UI);
        if (status != DX_SUCCESS)
            GST_ERROR("opening stream failed because there are no rights (license) to play the content (status: %d)", status);
        else {
            GST_INFO("playback rights found");

            /* starting consumption of the file - notifying the drm that the file is being used */
            status = DxDrmFile_HandleConsumptionEvent(m_DxDrmStream, DX_EVENT_START);
            if (status != DX_SUCCESS)
                GST_ERROR("Content consumption failed");
            else {
                GST_INFO("Stream was opened and is ready for playback");
                m_ready = true;
            }
        }

    } else if (m_state == PHASE_ACKNOWLEDGE) {
        uint32_t challengeLength = MAX_CHALLENGE_LEN;
        unsigned char* challenge = static_cast<unsigned char*>(g_malloc0(challengeLength));

        status = DxDrmClient_GetLicenseAcq_GenerateAck(&responseResult, challenge, &challengeLength);
        if (status != DX_SUCCESS)
            GST_ERROR("failed generating license ack challenge (status: %d, response result %p)", status, responseResult);

        GST_MEMDUMP("generated license ack request :", challenge, challengeLength);

        nextMessage = Uint8Array::create(challenge, challengeLength);
        g_free(challenge);
    }

    systemCode = status;

    return (status == DX_SUCCESS);
}
Exemplo n.º 18
0
static GstFlowReturn
gst_vdp_h264_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
    GstBuffer * buf, gboolean at_eos, GstVideoFrame * frame)
{
  GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
  GstBitReader reader;
  GstNalUnit nal_unit;
  guint8 forbidden_zero_bit;

  guint8 *data;
  guint size;
  gint i;

  GstFlowReturn ret = GST_FLOW_OK;

  GST_MEMDUMP ("data", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));

  gst_bit_reader_init_from_buffer (&reader, buf);

  if (gst_bit_reader_get_remaining (&reader) <
      h264_dec->nal_length_size * 8 + 7)
    goto invalid_packet;

  /* skip nal_length or sync code */
  gst_bit_reader_skip_unchecked (&reader, h264_dec->nal_length_size * 8);

  forbidden_zero_bit = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);

  if (forbidden_zero_bit != 0) {
    GST_WARNING ("forbidden_zero_bit != 0");
    return GST_FLOW_ERROR;
  }

  nal_unit.ref_idc = gst_bit_reader_get_bits_uint16_unchecked (&reader, 2);
  GST_DEBUG ("nal_ref_idc: %u", nal_unit.ref_idc);

  /* read nal_unit_type */
  nal_unit.type = gst_bit_reader_get_bits_uint16_unchecked (&reader, 5);

  GST_DEBUG ("nal_unit_type: %u", nal_unit.type);
  if (nal_unit.type == 14 || nal_unit.type == 20) {
    if (!gst_bit_reader_skip (&reader, 24))
      goto invalid_packet;
  }
  nal_unit.IdrPicFlag = (nal_unit.type == 5 ? 1 : 0);

  data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8;
  size = gst_bit_reader_get_remaining (&reader) / 8;

  i = size - 1;
  while ((gint) size > 0 && data[i] == 0x00) {
    size--;
    i--;
  }

  if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_H264_FRAME_GOT_PRIMARY)) {
    if (nal_unit.type == GST_NAL_SPS || nal_unit.type == GST_NAL_PPS ||
        nal_unit.type == GST_NAL_SEI || nal_unit.type == GST_NAL_AU_DELIMITER ||
        (nal_unit.type >= 14 && nal_unit.type <= 18))
      ret =
          gst_base_video_decoder_have_frame (base_video_decoder, FALSE, &frame);
  }

  if (nal_unit.type >= GST_NAL_SLICE && nal_unit.type <= GST_NAL_SLICE_IDR) {
    GstH264Slice slice;

    if (!gst_h264_parser_parse_slice_header (h264_dec->parser, &slice, data,
            size, nal_unit))
      goto invalid_packet;

    if (slice.redundant_pic_cnt == 0) {
      if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_H264_FRAME_GOT_PRIMARY)) {
        GstH264Slice *p_slice;
        guint8 pic_order_cnt_type, p_pic_order_cnt_type;
        gboolean finish_frame = FALSE;

        p_slice = &(GST_H264_FRAME_CAST (frame)->slice_hdr);
        pic_order_cnt_type = slice.picture->sequence->pic_order_cnt_type;
        p_pic_order_cnt_type = p_slice->picture->sequence->pic_order_cnt_type;

        if (slice.frame_num != p_slice->frame_num)
          finish_frame = TRUE;

        else if (slice.picture != p_slice->picture)
          finish_frame = TRUE;

        else if (slice.bottom_field_flag != p_slice->bottom_field_flag)
          finish_frame = TRUE;

        else if (nal_unit.ref_idc != p_slice->nal_unit.ref_idc &&
            (nal_unit.ref_idc == 0 || p_slice->nal_unit.ref_idc == 0))
          finish_frame = TRUE;

        else if ((pic_order_cnt_type == 0 && p_pic_order_cnt_type == 0) &&
            (slice.pic_order_cnt_lsb != p_slice->pic_order_cnt_lsb ||
                slice.delta_pic_order_cnt_bottom !=
                p_slice->delta_pic_order_cnt_bottom))
          finish_frame = TRUE;

        else if ((p_pic_order_cnt_type == 1 && p_pic_order_cnt_type == 1) &&
            (slice.delta_pic_order_cnt[0] != p_slice->delta_pic_order_cnt[0] ||
                slice.delta_pic_order_cnt[1] !=
                p_slice->delta_pic_order_cnt[1]))
          finish_frame = TRUE;

        if (finish_frame)
          ret =
              gst_base_video_decoder_have_frame (base_video_decoder, FALSE,
              &frame);

      }

      if (!GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_H264_FRAME_GOT_PRIMARY)) {
        if (GST_H264_IS_I_SLICE (slice.type)
            || GST_H264_IS_SI_SLICE (slice.type))
          GST_VIDEO_FRAME_FLAG_SET (frame, GST_VIDEO_FRAME_FLAG_KEYFRAME);

        GST_H264_FRAME_CAST (frame)->slice_hdr = slice;
        GST_VIDEO_FRAME_FLAG_SET (frame, GST_H264_FRAME_GOT_PRIMARY);
      }
    }
    gst_h264_frame_add_slice ((GstH264Frame *) frame, buf);
  }

  if (nal_unit.type == GST_NAL_SPS) {
    if (!gst_h264_parser_parse_sequence (h264_dec->parser, data, size))
      goto invalid_packet;
  }

  if (nal_unit.type == GST_NAL_PPS) {
    if (!gst_h264_parser_parse_picture (h264_dec->parser, data, size))
      goto invalid_packet;
  }

  gst_buffer_unref (buf);
  return ret;

invalid_packet:
  GST_WARNING ("Invalid packet size!");
  gst_buffer_unref (buf);

  return GST_FLOW_OK;
}
Exemplo n.º 19
0
static gboolean
gst_vdp_h264_dec_set_sink_caps (GstBaseVideoDecoder * base_video_decoder,
    GstCaps * caps)
{
  GstVdpH264Dec *h264_dec;
  GstStructure *structure;
  const GValue *value;

  h264_dec = GST_VDP_H264_DEC (base_video_decoder);

  structure = gst_caps_get_structure (caps, 0);
  /* packetized video has a codec_data */
  if ((value = gst_structure_get_value (structure, "codec_data"))) {
    GstBuffer *buf;
    GstBitReader reader;
    guint8 version;
    guint8 n_sps, n_pps;
    gint i;

    GST_DEBUG_OBJECT (h264_dec, "have packetized h264");
    h264_dec->packetized = TRUE;

    buf = gst_value_get_buffer (value);
    GST_MEMDUMP ("avcC:", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));

    /* parse the avcC data */
    if (GST_BUFFER_SIZE (buf) < 7) {
      GST_ERROR_OBJECT (h264_dec, "avcC size %u < 7", GST_BUFFER_SIZE (buf));
      return FALSE;
    }

    gst_bit_reader_init_from_buffer (&reader, buf);

    READ_UINT8 (&reader, version, 8);
    if (version != 1)
      return FALSE;

    SKIP (&reader, 30);

    READ_UINT8 (&reader, h264_dec->nal_length_size, 2);
    h264_dec->nal_length_size += 1;
    GST_DEBUG_OBJECT (h264_dec, "nal length %u", h264_dec->nal_length_size);

    SKIP (&reader, 3);

    READ_UINT8 (&reader, n_sps, 5);
    for (i = 0; i < n_sps; i++) {
      guint16 sps_length;
      guint8 *data;

      READ_UINT16 (&reader, sps_length, 16);
      sps_length -= 1;
      SKIP (&reader, 8);

      data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8;
      if (!gst_h264_parser_parse_sequence (h264_dec->parser, data, sps_length))
        return FALSE;

      SKIP (&reader, sps_length * 8);
    }

    READ_UINT8 (&reader, n_pps, 8);
    for (i = 0; i < n_pps; i++) {
      guint16 pps_length;
      guint8 *data;

      READ_UINT16 (&reader, pps_length, 16);
      pps_length -= 1;
      SKIP (&reader, 8);

      data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8;
      if (!gst_h264_parser_parse_picture (h264_dec->parser, data, pps_length))
        return FALSE;

      SKIP (&reader, pps_length * 8);
    }
  }

  return TRUE;
}
Exemplo n.º 20
0
static GstBuffer *
gst_rtp_qdm2_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{
  GstRtpQDM2Depay *rtpqdm2depay;
  GstBuffer *outbuf;
  guint16 seq;

  rtpqdm2depay = GST_RTP_QDM2_DEPAY (depayload);

  {
    gint payload_len;
    guint8 *payload;
    guint avail;
    guint pos = 0;

    payload_len = gst_rtp_buffer_get_payload_len (buf);
    if (payload_len < 3)
      goto bad_packet;

    payload = gst_rtp_buffer_get_payload (buf);
    seq = gst_rtp_buffer_get_seq (buf);
    if (G_UNLIKELY (seq != rtpqdm2depay->nextseq)) {
      GST_DEBUG ("GAP in sequence number, Resetting data !");
      /* Flush previous data */
      flush_data (rtpqdm2depay);
      /* And store new timestamp */
      rtpqdm2depay->ptimestamp = rtpqdm2depay->timestamp;
      rtpqdm2depay->timestamp = GST_BUFFER_TIMESTAMP (buf);
      /* And that previous data will be pushed at the bottom */
    }
    rtpqdm2depay->nextseq = seq + 1;

    GST_DEBUG ("Payload size %d 0x%x sequence:%d", payload_len, payload_len,
        seq);

    GST_MEMDUMP ("Incoming payload", payload, payload_len);

    while (pos < payload_len) {
      switch (payload[pos]) {
        case 0x80:{
          GST_DEBUG ("Unrecognized 0x80 marker, skipping 12 bytes");
          pos += 12;
        }
          break;
        case 0xff:
          /* HEADERS */
          GST_DEBUG ("Headers");
          /* Store the incoming timestamp */
          rtpqdm2depay->ptimestamp = rtpqdm2depay->timestamp;
          rtpqdm2depay->timestamp = GST_BUFFER_TIMESTAMP (buf);
          /* flush the internal data if needed */
          flush_data (rtpqdm2depay);
          if (G_UNLIKELY (!rtpqdm2depay->configured)) {
            guint8 *ourdata;
            GstBuffer *codecdata;
            GstCaps *caps;

            /* First bytes are unknown */
            GST_MEMDUMP ("Header", payload + pos, 32);
            ourdata = payload + pos + 10;
            pos += 10;
            rtpqdm2depay->channs = GST_READ_UINT32_BE (payload + pos + 4);
            rtpqdm2depay->samplerate = GST_READ_UINT32_BE (payload + pos + 8);
            rtpqdm2depay->bitrate = GST_READ_UINT32_BE (payload + pos + 12);
            rtpqdm2depay->blocksize = GST_READ_UINT32_BE (payload + pos + 16);
            rtpqdm2depay->framesize = GST_READ_UINT32_BE (payload + pos + 20);
            rtpqdm2depay->packetsize = GST_READ_UINT32_BE (payload + pos + 24);
            /* 16 bit empty block (0x02 0x00) */
            pos += 30;
            GST_DEBUG
                ("channs:%d, samplerate:%d, bitrate:%d, blocksize:%d, framesize:%d, packetsize:%d",
                rtpqdm2depay->channs, rtpqdm2depay->samplerate,
                rtpqdm2depay->bitrate, rtpqdm2depay->blocksize,
                rtpqdm2depay->framesize, rtpqdm2depay->packetsize);

            /* Caps */
            codecdata = gst_buffer_new_and_alloc (48);
            memcpy (GST_BUFFER_DATA (codecdata), headheader, 20);
            memcpy (GST_BUFFER_DATA (codecdata) + 20, ourdata, 28);

            caps = gst_caps_new_simple ("audio/x-qdm2",
                "samplesize", G_TYPE_INT, 16,
                "rate", G_TYPE_INT, rtpqdm2depay->samplerate,
                "channels", G_TYPE_INT, rtpqdm2depay->channs,
                "codec_data", GST_TYPE_BUFFER, codecdata, NULL);
            gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), caps);
            gst_caps_unref (caps);
            rtpqdm2depay->configured = TRUE;
          } else {
            GST_DEBUG ("Already configured, skipping headers");
            pos += 40;
          }
          break;
        default:{
          /* Shuffled packet contents */
          guint packetid = payload[pos++];
          guint packettype = payload[pos++];
          guint packlen = payload[pos++];
          guint hsize = 2;

          GST_DEBUG ("Packet id:%d, type:0x%x, len:%d",
              packetid, packettype, packlen);

          /* Packets bigger than 0xff bytes have a type with the high bit set */
          if (G_UNLIKELY (packettype & 0x80)) {
            packettype &= 0x7f;
            packlen <<= 8;
            packlen |= payload[pos++];
            hsize = 3;
            GST_DEBUG ("Packet id:%d, type:0x%x, len:%d",
                packetid, packettype, packlen);
          }

          if (packettype > 0x7f) {
            GST_ERROR ("HOUSTON WE HAVE A PROBLEM !!!!");
          }
          add_packet (rtpqdm2depay, packetid, packlen + hsize,
              payload + pos - hsize);
          pos += packlen;
        }
      }
    }

    GST_DEBUG ("final pos %d", pos);

    avail = gst_adapter_available (rtpqdm2depay->adapter);
    if (G_UNLIKELY (avail)) {
      GST_DEBUG ("Pushing out %d bytes of collected data", avail);
      outbuf = gst_adapter_take_buffer (rtpqdm2depay->adapter, avail);
      GST_BUFFER_TIMESTAMP (outbuf) = rtpqdm2depay->ptimestamp;
      GST_DEBUG ("Outgoing buffer timestamp %" GST_TIME_FORMAT,
          GST_TIME_ARGS (rtpqdm2depay->ptimestamp));
      return outbuf;
    }
  }
  return NULL;

  /* ERRORS */
bad_packet:
  {
    GST_ELEMENT_WARNING (rtpqdm2depay, STREAM, DECODE,
        (NULL), ("Packet was too short"));
    return NULL;
  }
}
Exemplo n.º 21
0
static void
flush_data (GstRtpQDM2Depay * depay)
{
  guint i;
  guint avail;

  if ((avail = gst_adapter_available (depay->adapter)))
    gst_adapter_flush (depay->adapter, avail);

  GST_DEBUG ("Flushing %d packets", depay->nbpackets);

  for (i = 0; depay->packets[i]; i++) {
    QDM2Packet *pack = depay->packets[i];
    guint32 crc = 0;
    int i = 0;
    GstBuffer *buf;
    guint8 *data;

    /* CRC is the sum of everything (including first bytes) */

    data = pack->data;

    if (G_UNLIKELY (data == NULL))
      continue;

    /* If the packet size is bigger than 0xff, we need 2 bytes to store the size */
    if (depay->packetsize > 0xff) {
      /* Expanded size 0x02 | 0x80 */
      data[0] = 0x82;
      GST_WRITE_UINT16_BE (data + 1, depay->packetsize - 3);
    } else {
      data[0] = 0x2;
      data[1] = depay->packetsize - 2;
    }

    /* Calculate CRC */
    for (; i < depay->packetsize; i++)
      crc += data[i];

    GST_DEBUG ("CRC is 0x%x", crc);

    /* Write CRC */
    if (depay->packetsize > 0xff)
      GST_WRITE_UINT16_BE (data + 3, crc);
    else
      GST_WRITE_UINT16_BE (data + 2, crc);

    GST_MEMDUMP ("Extracted packet", data, depay->packetsize);

    buf = gst_buffer_new ();
    GST_BUFFER_DATA (buf) = data;
    GST_BUFFER_MALLOCDATA (buf) = data;
    GST_BUFFER_SIZE (buf) = depay->packetsize;

    gst_adapter_push (depay->adapter, buf);

    if (pack->data) {
      pack->data = NULL;
    }
  }
}
/**
 * gst_mpegts_parse_descriptors:
 * @buffer: (transfer none): descriptors to parse
 * @buf_len: Size of @buffer
 *
 * Parses the descriptors present in @buffer and returns them as an
 * array.
 *
 * Note: The data provided in @buffer will not be copied.
 *
 * Returns: (transfer full) (element-type GstMpegtsDescriptor): an
 * array of the parsed descriptors or %NULL if there was an error.
 * Release with #g_array_unref when done with it.
 */
GPtrArray *
gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len)
{
  GPtrArray *res;
  guint8 length;
  guint8 *data;
  guint i, nb_desc = 0;

  /* fast-path */
  if (buf_len == 0)
    return g_ptr_array_new ();

  data = buffer;

  GST_MEMDUMP ("Full descriptor array", buffer, buf_len);

  while (data - buffer < buf_len) {
    data++;                     /* skip tag */
    length = *data++;

    if (data - buffer > buf_len) {
      GST_WARNING ("invalid descriptor length %d now at %d max %"
          G_GSIZE_FORMAT, length, (gint) (data - buffer), buf_len);
      return NULL;
    }

    data += length;
    nb_desc++;
  }

  GST_DEBUG ("Saw %d descriptors, read %" G_GSIZE_FORMAT " bytes",
      nb_desc, (gsize) (data - buffer));

  if (data - buffer != buf_len) {
    GST_WARNING ("descriptors size %d expected %" G_GSIZE_FORMAT,
        (gint) (data - buffer), buf_len);
    return NULL;
  }

  res =
      g_ptr_array_new_full (nb_desc + 1,
      (GDestroyNotify) gst_mpegts_descriptor_free);

  data = buffer;

  for (i = 0; i < nb_desc; i++) {
    GstMpegtsDescriptor *desc = g_slice_new0 (GstMpegtsDescriptor);

    desc->data = data;
    desc->tag = *data++;
    desc->length = *data++;
    /* Copy the data now that we known the size */
    desc->data = g_memdup (desc->data, desc->length + 2);
    GST_LOG ("descriptor 0x%02x length:%d", desc->tag, desc->length);
    GST_MEMDUMP ("descriptor", desc->data + 2, desc->length);
    /* extended descriptors */
    if (G_UNLIKELY (desc->tag == 0x7f))
      desc->tag_extension = *data;

    data += desc->length;

    /* Set the descriptor in the array */
    g_ptr_array_index (res, i) = desc;
  }

  res->len = nb_desc;

  return res;
}
Exemplo n.º 23
0
gboolean
id3demux_id3v2_parse_frame (ID3TagsWorking * work)
{
  const gchar *tag_name;
  gboolean result = FALSE;
  gint i;
  guint8 *frame_data = work->hdr.frame_data;
  guint frame_data_size = work->cur_frame_size;
  gchar *tag_str = NULL;
  GArray *tag_fields = NULL;
  guint8 *uu_data = NULL;

#ifdef HAVE_ZLIB
  guint8 *uncompressed_data = NULL;
#endif

  /* Check that the frame id is valid */
  for (i = 0; i < 5 && work->frame_id[i] != '\0'; i++) {
    if (!g_ascii_isalnum (work->frame_id[i])) {
      GST_DEBUG ("Encountered invalid frame_id");
      return FALSE;
    }
  }

  /* Can't handle encrypted frames right now (in case we ever do, we'll have
   * to do the decryption after the un-unsynchronisation and decompression,
   * not here) */
  if (work->frame_flags & ID3V2_FRAME_FORMAT_ENCRYPTION) {
    GST_WARNING ("Encrypted frames are not supported");
    return FALSE;
  }

  tag_name = gst_tag_from_id3_tag (work->frame_id);
  if (tag_name == NULL &&
      strncmp (work->frame_id, "RVA2", 4) != 0 &&
      strncmp (work->frame_id, "TXXX", 4) != 0 &&
      strncmp (work->frame_id, "TDAT", 4) != 0 &&
      strncmp (work->frame_id, "UFID", 4) != 0) {
    return FALSE;
  }

  if (work->frame_flags & (ID3V2_FRAME_FORMAT_COMPRESSION |
          ID3V2_FRAME_FORMAT_DATA_LENGTH_INDICATOR)) {
    if (work->hdr.frame_data_size <= 4)
      return FALSE;
    if (ID3V2_VER_MAJOR (work->hdr.version) == 3) {
      work->parse_size = GST_READ_UINT32_BE (frame_data);
    } else {
      work->parse_size = read_synch_uint (frame_data, 4);
    }
    frame_data += 4;
    frame_data_size -= 4;
    GST_LOG ("Un-unsynced data size %d (of %d)", work->parse_size,
        frame_data_size);
    if (work->parse_size > frame_data_size) {
      GST_WARNING ("ID3v2 frame %s data has invalid size %d (>%d)",
          work->frame_id, work->parse_size, frame_data_size);
      return FALSE;
    }
  }

  /* in v2.3 the frame sizes are not syncsafe, so the entire tag had to be
   * unsynced. In v2.4 the frame sizes are syncsafe so it's just the frame
   * data that needs un-unsyncing, but not the frame headers. */
  if (ID3V2_VER_MAJOR (work->hdr.version) == 4) {
    if ((work->hdr.flags & ID3V2_HDR_FLAG_UNSYNC) != 0 ||
        ((work->frame_flags & ID3V2_FRAME_FORMAT_UNSYNCHRONISATION) != 0)) {
      GST_DEBUG ("Un-unsyncing frame %s", work->frame_id);
      uu_data = id3demux_ununsync_data (frame_data, &frame_data_size);
      frame_data = uu_data;
      GST_MEMDUMP ("ID3v2 frame (un-unsyced)", frame_data, frame_data_size);
    }
  }

  work->parse_size = frame_data_size;

  if (work->frame_flags & ID3V2_FRAME_FORMAT_COMPRESSION) {
#ifdef HAVE_ZLIB
    uLongf destSize = work->parse_size;
    Bytef *dest, *src;

    uncompressed_data = g_malloc (work->parse_size);

    dest = (Bytef *) uncompressed_data;
    src = (Bytef *) frame_data;

    if (uncompress (dest, &destSize, src, frame_data_size) != Z_OK) {
      g_free (uncompressed_data);
      g_free (uu_data);
      return FALSE;
    }
    if (destSize != work->parse_size) {
      GST_WARNING
          ("Decompressing ID3v2 frame %s did not produce expected size %d bytes (got %lu)",
          tag_name, work->parse_size, destSize);
      g_free (uncompressed_data);
      g_free (uu_data);
      return FALSE;
    }
    work->parse_data = uncompressed_data;
#else
    GST_WARNING ("Compressed ID3v2 tag frame could not be decompressed"
        " because gstid3demux was compiled without zlib support");
    g_free (uu_data);
    return FALSE;
#endif
  } else {
    work->parse_data = frame_data;
  }

  if (work->frame_id[0] == 'T') {
    if (strcmp (work->frame_id, "TDAT") == 0) {
      parse_obsolete_tdat_frame (work);
      result = TRUE;
    } else if (strcmp (work->frame_id, "TXXX") == 0) {
      /* Handle user text frame */
      tag_str = parse_user_text_identification_frame (work, &tag_name);
    } else {
      /* Text identification frame */
      tag_fields = parse_text_identification_frame (work);
    }
  } else if (work->frame_id[0] == 'W' && strcmp (work->frame_id, "WXXX") != 0) {
    /* URL link frame: ISO-8859-1 encoded, one frame per tag */
    tag_str = parse_url_link_frame (work, &tag_name);
  } else if (!strcmp (work->frame_id, "COMM")) {
    /* Comment */
    result = parse_comment_frame (work);
  } else if (!strcmp (work->frame_id, "APIC")) {
    /* Attached picture */
    result = parse_picture_frame (work);
  } else if (!strcmp (work->frame_id, "RVA2")) {
    /* Relative volume */
    result = parse_relative_volume_adjustment_two (work);
  } else if (!strcmp (work->frame_id, "UFID")) {
    /* Unique file identifier */
    tag_str = parse_unique_file_identifier (work, &tag_name);
  }
#ifdef HAVE_ZLIB
  if (work->frame_flags & ID3V2_FRAME_FORMAT_COMPRESSION) {
    g_free (uncompressed_data);
    uncompressed_data = NULL;
    work->parse_data = frame_data;
  }
#endif

  if (tag_str != NULL) {
    /* g_print ("Tag %s value %s\n", tag_name, tag_str); */
    result = id3v2_tag_to_taglist (work, tag_name, tag_str);
    g_free (tag_str);
  }
  if (tag_fields != NULL) {
    if (strcmp (work->frame_id, "TCON") == 0) {
      /* Genre strings need special treatment */
      result |= id3v2_genre_fields_to_taglist (work, tag_name, tag_fields);
    } else {
      gint t;

      for (t = 0; t < tag_fields->len; t++) {
        tag_str = g_array_index (tag_fields, gchar *, t);
        if (tag_str != NULL && tag_str[0] != '\0')
          result |= id3v2_tag_to_taglist (work, tag_name, tag_str);
      }
    }
    free_tag_strings (tag_fields);
  }

  g_free (uu_data);

  return result;
}
static void
check_1x1_buffer (GstBuffer * buf, GstCaps * caps)
{
  GstVideoInfo info;
  GstVideoFrame frame;
  /* the exact values we check for come from videotestsrc */
  static const guint yuv_values[] = { 81, 90, 240, 255 };
  static const guint rgb_values[] = { 0xff, 0, 0, 255 };
  static const guint gray8_values[] = { 0x51 };
  static const guint gray16_values[] = { 0x5151 };
  const guint *values;
  guint i;
  const GstVideoFormatInfo *finfo;

  fail_unless (buf != NULL);
  fail_unless (caps != NULL);

  fail_unless (gst_video_info_from_caps (&info, caps));
  fail_unless (gst_video_frame_map (&frame, &info, buf, GST_MAP_READ));

  finfo = info.finfo;

  if (GST_VIDEO_INFO_IS_YUV (&info))
    values = yuv_values;
  else if (GST_VIDEO_INFO_IS_GRAY (&info))
    if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 8)
      values = gray8_values;
    else
      values = gray16_values;
  else
    values = rgb_values;

  GST_MEMDUMP ("buffer", GST_VIDEO_FRAME_PLANE_DATA (&frame, 0), 8);

  for (i = 0; i < GST_VIDEO_FRAME_N_COMPONENTS (&frame); i++) {
    guint8 *data = GST_VIDEO_FRAME_COMP_DATA (&frame, i);

    GST_DEBUG ("W: %d", GST_VIDEO_FORMAT_INFO_W_SUB (finfo, i));
    GST_DEBUG ("H: %d", GST_VIDEO_FORMAT_INFO_H_SUB (finfo, i));

    if (GST_VIDEO_FORMAT_INFO_W_SUB (finfo,
            i) >= GST_VIDEO_FRAME_WIDTH (&frame))
      continue;
    if (GST_VIDEO_FORMAT_INFO_H_SUB (finfo,
            i) >= GST_VIDEO_FRAME_HEIGHT (&frame))
      continue;

    if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 8) {
      fail_unless_equals_int (data[0], values[i]);
    } else if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 16) {
      guint16 pixels, val;
      gint depth;

      if (GST_VIDEO_FORMAT_INFO_IS_LE (finfo))
        pixels = GST_READ_UINT16_LE (data);
      else
        pixels = GST_READ_UINT16_BE (data);

      depth = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, i);
      val = pixels >> GST_VIDEO_FORMAT_INFO_SHIFT (finfo, i);
      val = val & ((1 << depth) - 1);

      GST_DEBUG ("val %08x %d : %d", pixels, i, val);
      if (depth <= 8) {
        fail_unless_equals_int (val, values[i] >> (8 - depth));
      } else {