+++ /dev/null
-/*
- * libmm-player
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
- * YoungHwan An <younghwan_.an@samsung.com>, naveen cherukuri <naveen.ch@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef __MM_PLAYER_AHS_H__
-#define __MM_PLAYER_AHS_H__
-
-#include <glib.h>
-#include "mm_player_ahs_hls.h"
-#include <gst/gst.h>
-#include <gst/app/gstappsrc.h>
-#include <gst/app/gstappsink.h>
-#include <string.h>
-#include "mm_debug.h"
-
-#define HLS_POSIX_PATH_MAX 256
-#define HLS_MANIFEST_DEFAULT_PATH "/opt/media/"
-#define HLS_MANIFEST_DEFAULT_FILE_NAME HLS_MANIFEST_DEFAULT_PATH"XXXXXX"
-
-typedef struct
-{
- void *ahs_client;
- GstElement *appsrc; /* appsrc to push data */
-
- int uri_type;
- gboolean need_bw_switch;
-
- /* manifest file (mf) uris */
- gchar *main_mf_uri;
-
- /* user agent */
- gchar *user_agent;
-
- gchar *cur_mf_uri;
- gchar *cur_media_uri;
- gchar *cur_key_uri;
- gchar cur_key_data[16];
- char cur_iv[16];
-
- char ahs_manifest_dmp_location[HLS_POSIX_PATH_MAX]; /* manifest file dumped location */
- char ahs_key_dmp_location [HLS_POSIX_PATH_MAX];
-
- int ahs_state;
- GMutex* state_lock;
-
- /* manifest/playlist download */
- GThread *manifest_thread;
- gboolean manifest_thread_exit;
- GstElement *manifest_download_pipeline;
- GstElement *manifest_download_src;
- GstElement *manifest_download_sink;
- GCond* manifest_start_cond;
- GCond* manifest_update_cond;
- GCond* manifest_eos_cond;
- GCond* manifest_exit_cond;
- GMutex* manifest_mutex;
-
- /* media download */
- GThread *media_thread;
- GMutex *media_mutex;
- gboolean media_thread_exit;
- GstElement *media_download_pipeline;
- GstElement *media_download_src;
- GstElement *media_download_sink;
- GCond *media_eos_cond;
- GCond *media_start_cond;
-
- /* key download */
- GstElement *key_download_pipeline;
- GstElement *key_download_src;
- GstElement *key_download_sink;
- GCond *key_eos_cond;
-
- guint64 seg_start_time; /* segment start time in usec*/
- guint64 seg_end_time; /* segment end time usec*/
- guint download_rate;
- guint64 seg_size;
- gint cache_frag_count;
-
- gboolean hls_is_wait_for_reload;
-
- GCond* tmp_cond;
-
- gboolean is_initialized;
-}mm_player_ahs_t;
-
-
-
-mm_player_ahs_t * __mm_player_ahs_create ();
-gboolean __mm_player_ahs_initialize (mm_player_ahs_t *ahs_player, int uri_type, char *uri, GstElement *appsrc);
-gboolean __mm_player_ahs_start (mm_player_ahs_t *ahs_player);
-gboolean __mm_player_ahs_deinitialize (mm_player_ahs_t *ahs_player);
-gboolean __mm_player_ahs_stop (mm_player_ahs_t *ahs_player);
-gboolean __mm_player_ahs_destroy (mm_player_ahs_t *ahs_player);
-gboolean
-ahs_store_media_presentation (mm_player_ahs_t *ahs_player, unsigned char *buffer, unsigned int buffer_len);
-gboolean ahs_check_allow_cache (mm_player_ahs_t *ahs_player);
-#endif
-
+++ /dev/null
-/*
- * libmm-player
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
- * YoungHwan An <younghwan_.an@samsung.com>, naveen cherukuri <naveen.ch@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef __MM_PLAYER_AHS_HLS_H__
-#define __MM_PLAYER_AHS_HLS_H__
-
-#include "mm_player_m3u8.h"
-#include <glib.h>
-#include <gst/gst.h>
-#include "mm_debug.h"
-#include <string.h>
-#include <openssl/evp.h>
-#include <openssl/aes.h>
-
-typedef struct
-{
- gchar *uri;
- EVP_CIPHER_CTX decrypt;
- GstM3U8Client *client;
- GstBuffer *remained; /* remained data in aes decryption */
- gboolean discontinuity; /* discontinuity flag */
- GList *list_to_switch;
- FILE *allow_cache_fd;
-}mm_player_hls_t;
-#define DEFAULT_FRAGMENTS_CACHE 2
-
-
-void * __mm_player_hls_create ();
-gboolean __mm_player_hls_destroy (void *hls_handle);
-gboolean __mm_player_hls_initialize (void *hls_handle, gchar *uri);
-gboolean hls_decryption_initialize (void *hls_handle, gchar *key_data, unsigned char *iv);
-gboolean hls_decrypt_media_fragment (void *hls_handle,GstBuffer *InBuf, GstBuffer **OutBuf);
-gboolean hls_get_next_media_fragment (void *hls_handle, gchar **media_uri, gchar **key_uri, char **iv);
-gboolean hls_switch_playlist (void *hls_handle, guint download_rate, gboolean *need_bw_switch);
-gboolean hls_playlist_update_interval (void *hls_handle, GTimeVal *next_update);
-gboolean hls_has_variant_playlist (void *hls_handle);
-gchar *hls_get_current_playlist (mm_player_hls_t *hls_player);
-gboolean hls_set_current_playlist (mm_player_hls_t *hls_player);
-gboolean hls_parse_playlist_update_client (void *hls_handle, char* playlist);
-gboolean hls_client_is_live (void *hls_handle);
-gboolean hls_determining_next_file_load (void *hls_handle, gboolean *is_ready);
-gboolean hls_is_buffer_discontinuous (void *hls_handle);
-gboolean hls_downloaded_variant_playlist (void *hls_handle, gchar *cur_mf_uri);
-gboolean hls_clear_discontinuous (void *hls_handle);
-gboolean hls_check_allow_cache (void *hls_handle);
-gboolean hls_store_media_presentation (void *hls_handle, unsigned char *buffer, unsigned int buffer_len);
-#endif
-
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com>
- * Copyright (C) 2010 Andoni Morales Alastruey <ylatuya@gmail.com>
- *
- * m3u8.h:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* This source code is taken from m3u8.c, which is licensed by GNU Library General Public License.
- * AES-128 bit decryption features are changed from m3u8.c.
- * - gst_m3u8_update and gst_m3u8_media_file_new are modified.
- * - gst_m3u8_getIV_from_mediasequence is added.
- * For convenience,
- * - gst_m3u8_client_get_next_fragment is modified.
- * - gst_m3u8_client_check_next_fragment is added.
- * File name is changed to mm_player_m3u8.c
- */
-
-
-#ifndef __MM_PLAYER_M3U8_H__
-#define __MM_PLAYER_M3U8_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS typedef struct _GstM3U8 GstM3U8;
-typedef struct _GstM3U8MediaFile GstM3U8MediaFile;
-typedef struct _GstM3U8Client GstM3U8Client;
-
-#define GST_M3U8_MEDIA_FILE(f) ((GstM3U8MediaFile*)f)
-
-struct _GstM3U8
-{
- gchar *uri;
-
- gboolean endlist; /* if ENDLIST has been reached */
- gint version; /* last EXT-X-VERSION */
- gint targetduration; /* last EXT-X-TARGETDURATION */
- gchar *allowcache; /* last EXT-X-ALLOWCACHE */
-
- gint bandwidth;
- gint program_id;
- gchar *codecs;
- gint width;
- gint height;
- GList *files;
-
- /*< private > */
- gchar *last_data;
- GList *lists; /* list of GstM3U8 from the main playlist */
- GstM3U8 *parent; /* main playlist (if any) */
- guint mediasequence; /* EXT-X-MEDIA-SEQUENCE & increased with new media file */
-};
-
-struct _GstM3U8MediaFile
-{
- gchar *title;
- gint duration;
- gchar *uri;
- guint sequence; /* the sequence nb of this file */
-
- gchar *key_url;
- unsigned char key[16];
- unsigned char iv[16];
-
-};
-
-struct _GstM3U8Client
-{
- GstM3U8 *main; /* main playlist */
- GstM3U8 *current;
- guint update_failed_count;
- gint sequence; /* the next sequence for this client */
-};
-
-
-GstM3U8Client *gst_m3u8_client_new (const gchar * uri);
-void gst_m3u8_client_free (GstM3U8Client * client);
-gboolean gst_m3u8_client_update (GstM3U8Client * client, gchar * data);
-void gst_m3u8_client_set_current (GstM3U8Client * client, GstM3U8 * m3u8);
-const GstM3U8MediaFile *gst_m3u8_client_get_next_fragment (GstM3U8Client * client, gboolean * discontinuity);
-#define gst_m3u8_client_get_uri(Client) ((Client)->main->uri)
-#define gst_m3u8_client_has_variant_playlist(Client) ((Client)->main->lists)
-#define gst_m3u8_client_is_live(Client) (!(Client)->current->endlist)
-#define gst_m3u8_client_allow_cache(Client) ((Client)->current->allowcache)
-
-const gboolean gst_m3u8_client_check_next_fragment (GstM3U8Client * client);
-
-G_END_DECLS
-#endif /* __MM_PLAYER_M3U8_H__ */
+++ /dev/null
-/*
- * libmm-player
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
- * YoungHwan An <younghwan_.an@samsung.com>, naveen cherukuri <naveen.ch@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-#include <vconf.h>
-#include "mm_player_ahs.h"
-#include "mm_player_priv.h"
-#include "mm_player_utils.h"
-
-char *state_string[] = { "STATE_STOP", "STATE_PREPARE_MANIFEST", "STATE_MEDIA_STREAMING" };
-
-enum
-{
- AHS_STATE_STOP = 0,
- AHS_STATE_PREPARE_MANIFEST,
- AHS_STATE_MEDIA_STREAMING,
-} AHS_STATE;
-
-enum
-{
- STATE_STOP = 0,
- STATE_PREPARE_PLAYLIST,
- STATE_MEDIA_STREAMING
-} HLS_STATE;
-
-static gpointer manifest_update_thread(gpointer data);
-static gpointer media_download_thread (gpointer data);
-static gboolean ahs_client_is_live (mm_player_ahs_t *ahs_player);
-static gboolean ahs_manifest_get_update_interval (mm_player_ahs_t *ahs_player, GTimeVal *next_update);
-static gboolean ahs_create_manifest_download_pipeline (mm_player_ahs_t *ahs_player);
-static gboolean ahs_create_key_download_pipeline (mm_player_ahs_t *ahs_player);
-static gboolean ahs_create_media_download_pipeline (mm_player_ahs_t *ahs_player);
-static gboolean ahs_parse_manifest_update_client (mm_player_ahs_t *ahs_player);
-static gboolean ahs_manifest_download_callback(GstBus *bus, GstMessage *msg, gpointer data);
-static gboolean ahs_key_download_callback(GstBus *bus, GstMessage *msg, gpointer data);
-static gboolean ahs_media_download_callback(GstBus *bus, GstMessage *msg, gpointer data);
-static gboolean ahs_determining_next_file_load (mm_player_ahs_t *ahs_player, gboolean *is_ready);
-static gboolean ahs_set_current_manifest (mm_player_ahs_t *ahs_player);
-static gchar* ahs_get_current_manifest (mm_player_ahs_t *ahs_player);
-static gboolean ahs_switch_playlist (mm_player_ahs_t *ahs_player, guint download_rate);
-static gboolean ahs_get_next_media_uri (mm_player_ahs_t *ahs_player, gchar **media_uri, gchar **key_uri, char **iv);
-static gboolean ahs_decrypt_media (mm_player_ahs_t *ahs_player,GstBuffer *InBuf, GstBuffer **OutBuf);
-static gboolean ahs_destory_manifest_download_pipeline(mm_player_ahs_t *ahs_player);
-static gboolean ahs_destory_media_download_pipeline(mm_player_ahs_t *ahs_player);
-static gboolean ahs_destory_key_download_pipeline(mm_player_ahs_t *ahs_player);
-static gboolean ahs_is_buffer_discontinuous (mm_player_ahs_t *ahs_player);
-static gboolean ahs_clear_discontinuous (mm_player_ahs_t *ahs_player);
-
-static void
-on_new_buffer_from_appsink (GstElement * appsink, void* data)
-{
- mm_player_ahs_t *ahs_player = (mm_player_ahs_t*) data;
- GstBuffer *InBuf = NULL;
- GstFlowReturn fret = GST_FLOW_OK;
-
- InBuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
-
- if (InBuf && ahs_player->appsrc)
- {
- ahs_player->seg_size = ahs_player->seg_size + GST_BUFFER_SIZE (InBuf);
-
- //g_print ("******** Pushing buffer size = %d and total_seg_size = %"G_GUINT64_FORMAT"\n", GST_BUFFER_SIZE (InBuf), ahs_player->seg_size);
-
- if (ahs_player->cur_key_uri)
- {
- GstBuffer *OutBuf = NULL;
-
- ahs_decrypt_media (ahs_player, InBuf, &OutBuf);
-
- gst_buffer_unref (InBuf);
-
- /* FIXME : Reset Buffer property */
- GST_BUFFER_TIMESTAMP (OutBuf) = GST_CLOCK_TIME_NONE;
- GST_BUFFER_DURATION (OutBuf) = GST_CLOCK_TIME_NONE;
- GST_BUFFER_FLAGS(OutBuf) = 0;
-
- if (ahs_is_buffer_discontinuous(ahs_player))
- {
- g_print ("\n\n\n\nMarking fragment as discontinuous...\n\n\n\n\n");
- GST_BUFFER_FLAG_SET (OutBuf, GST_BUFFER_FLAG_DISCONT);
- ahs_clear_discontinuous (ahs_player);
- }
-
- fret = gst_app_src_push_buffer ((GstAppSrc *)ahs_player->appsrc, OutBuf);
- if (fret != GST_FLOW_OK)
- {
- g_print ("\n\nError in pushing buffer to appsrc: reason - %s\n\n", gst_flow_get_name(fret));
- __mm_player_ahs_stop (ahs_player);
- }
-
- }
- else
- {
- /* FIXME : Reset Buffer property */
- GST_BUFFER_TIMESTAMP (InBuf) = GST_CLOCK_TIME_NONE;
- GST_BUFFER_DURATION (InBuf) = GST_CLOCK_TIME_NONE;
- GST_BUFFER_FLAGS(InBuf) = 0;
-
- if (ahs_is_buffer_discontinuous(ahs_player))
- {
- g_print ("\n\n\n\n \t\t((((((((((((((((((((((( Marking fragment as discontinuous... ))))))))))))))))))))))))\n\n\n\n\n");
- GST_BUFFER_FLAG_SET (InBuf, GST_BUFFER_FLAG_DISCONT);
- ahs_clear_discontinuous (ahs_player);
- }
-
- fret = gst_app_src_push_buffer ((GstAppSrc *)ahs_player->appsrc, InBuf);
- if (fret != GST_FLOW_OK)
- {
- g_print ("\n\nError in pushing buffer to appsrc: reason - %s\n\n", gst_flow_get_name(fret));
- __mm_player_ahs_stop (ahs_player);
- }
- }
- }
- else
- {
- debug_warning ("Pulled buffer is not valid!!!\n");
- }
-}
-
-static gpointer
-manifest_update_thread(gpointer data)
-{
- mm_player_ahs_t *ahs_player = (mm_player_ahs_t*) data;
- gboolean bret = FALSE;
- GTimeVal next_update = {0, };
- GTimeVal tmp_update = {0, };
- guint64 start = 0;
- guint64 stop = 0;
-
- debug_log ("Waiting for trigger to start downloading manifest...\n");
- g_mutex_lock (ahs_player->manifest_mutex);
- g_cond_wait (ahs_player->manifest_update_cond, ahs_player->manifest_mutex);
- g_mutex_unlock (ahs_player->manifest_mutex);
-
- while (1)
- {
- g_mutex_lock (ahs_player->manifest_mutex);
- if (ahs_player->manifest_thread_exit == TRUE)
- {
- g_mutex_unlock (ahs_player->manifest_mutex);
- goto exit;
- }
- g_mutex_unlock (ahs_player->manifest_mutex);
-
- next_update.tv_sec = 0;
- next_update.tv_usec = 0;
-
- g_get_current_time (&next_update);
-
- start = (next_update.tv_sec * 1000000)+ next_update.tv_usec;
-
- /* download manifest file */
- bret = ahs_create_manifest_download_pipeline (ahs_player);
- if (FALSE == bret)
- {
- goto exit;
- }
-
- /* waiting for playlist to be downloaded */
- g_mutex_lock (ahs_player->manifest_mutex);
- if (ahs_player->manifest_thread_exit == TRUE)
- {
- g_mutex_unlock (ahs_player->manifest_mutex);
- goto exit;
- }
- debug_log ("waiting for manifest file to be downloaded...waiting on manifest eos cond\n");
- g_cond_wait (ahs_player->manifest_eos_cond, ahs_player->manifest_mutex);
- g_mutex_unlock (ahs_player->manifest_mutex);
-
- if (ahs_client_is_live (ahs_player))
- {
- ahs_manifest_get_update_interval (ahs_player, &next_update);
-
- stop = (next_update.tv_sec * 1000000)+ next_update.tv_usec;
-
- g_mutex_lock (ahs_player->manifest_mutex);
- if (ahs_player->manifest_thread_exit == TRUE)
- {
- g_mutex_unlock (ahs_player->manifest_mutex);
- goto exit;
- }
- debug_log ("Next update scheduled at %s\n", g_time_val_to_iso8601 (&next_update));
- bret = g_cond_timed_wait (ahs_player->manifest_update_cond, ahs_player->manifest_mutex, &next_update);
-
- g_mutex_unlock (ahs_player->manifest_mutex);
-#if 1
- tmp_update.tv_sec = 0;
- tmp_update.tv_usec = 0;
-
- g_get_current_time (&tmp_update);
-
- if (bret == TRUE)
- {
- debug_log ("\n\n@@@@@@@@@ Sombody signalled manifest waiting... going to update current manifest file and diff = %d\n\n\n",
- ((next_update.tv_sec * 1000000)+ next_update.tv_usec) - ((tmp_update.tv_sec * 1000000)+ tmp_update.tv_usec));
- }
- else
- {
- debug_log ("\n\n\n~~~~~~~~~~~Timeout happened, need to update current manifest file and diff = %d\n\n\n",
- ((next_update.tv_sec * 1000000)+ next_update.tv_usec) - ((tmp_update.tv_sec * 1000000)+ tmp_update.tv_usec));
- }
-#endif
- }
- else
- {
- g_mutex_lock (ahs_player->manifest_mutex);
- if (ahs_player->manifest_thread_exit == TRUE)
- {
- g_mutex_unlock (ahs_player->manifest_mutex);
- goto exit;
- }
- g_print ("NOT-LIVE : Waiting for trigger to start downloading manifest...\n");
- g_cond_wait (ahs_player->manifest_update_cond, ahs_player->manifest_mutex);
- g_mutex_unlock (ahs_player->manifest_mutex);
-
- }
- }
-
-exit:
- debug_log ("Exiting from manifest thread...\n");
- ahs_player->manifest_thread_exit = TRUE;
- g_thread_exit (ahs_player->manifest_thread);
-
- return NULL;
-
-}
-
-static gpointer
-media_download_thread (gpointer data)
-{
- mm_player_ahs_t *ahs_player = (mm_player_ahs_t*) data;
- gboolean bret = FALSE;
- gchar *media_uri = NULL;
- gchar *key_uri = NULL;
- GTimeVal time = {0, };
- GstFlowReturn fret = GST_FLOW_OK;
- char *iv = (char *) malloc (16);
- if (iv == NULL)
- {
- g_print ("ERRORR");
- return NULL;
- }
-
- g_mutex_lock (ahs_player->media_mutex);
- g_cond_wait(ahs_player->media_start_cond, ahs_player->media_mutex);
- g_mutex_unlock (ahs_player->media_mutex);
-
- debug_log ("Received received manifest file...Moving to media download\n");
-
- while (1)
- {
- g_mutex_lock (ahs_player->media_mutex);
- if (ahs_player->media_thread_exit)
- {
- g_mutex_unlock (ahs_player->media_mutex);
- goto exit;
- }
- g_mutex_unlock (ahs_player->media_mutex);
-
- if (ahs_player->need_bw_switch)
- {
- debug_log ("Need to Switch BW, start updating new switched URI...\n");
- g_cond_signal (ahs_player->manifest_update_cond);
- g_mutex_lock (ahs_player->manifest_mutex);
- if (ahs_player->media_thread_exit)
- {
- g_mutex_unlock (ahs_player->manifest_mutex);
- goto exit;
- }
- debug_log ("waiting for manifest eos in media download thread...\n");
- g_cond_wait (ahs_player->manifest_eos_cond, ahs_player->manifest_mutex);
- g_mutex_unlock (ahs_player->manifest_mutex);
-
- }
-
- media_uri = NULL;
- key_uri = NULL;
-
- /* Get next media file to download */
- bret = ahs_get_next_media_uri (ahs_player, &media_uri, &key_uri, &iv);
- if (FALSE == bret)
- {
- ahs_player->media_thread_exit = TRUE;
- fret = gst_app_src_end_of_stream ((GstAppSrc *)ahs_player->appsrc);
- if (GST_FLOW_OK != fret)
- {
- g_print ("Error in pushing EOS to appsrc : reason - %s", gst_flow_get_name (fret));
- }
- goto exit;
- }
-
- if (NULL == media_uri)
- {
- if (ahs_client_is_live (ahs_player))
- {
- g_cond_signal (ahs_player->manifest_update_cond);
- g_mutex_lock (ahs_player->manifest_mutex);
- if (ahs_player->media_thread_exit)
- {
- g_mutex_unlock (ahs_player->manifest_mutex);
- goto exit;
- }
- debug_log ("waiting for manifest eos in media download thread...\n");
- g_cond_wait (ahs_player->manifest_eos_cond, ahs_player->manifest_mutex);
- g_mutex_unlock (ahs_player->manifest_mutex);
- continue;
- }
- else
- {
- ahs_player->media_thread_exit = TRUE;
- g_print ("media download thread exiting....");
- fret = gst_app_src_end_of_stream ((GstAppSrc *)ahs_player->appsrc);
- if (GST_FLOW_OK != fret)
- {
- g_print ("Error in pushing EOS to appsrc : reason - %s", gst_flow_get_name (fret));
- }
- goto exit;
- }
- }
-
- if (key_uri)
- {
- if (ahs_player->cur_key_uri)
- {
- g_free (ahs_player->cur_key_uri);
- ahs_player->cur_key_uri = NULL;
- }
-
- ahs_player->cur_key_uri = g_strdup (key_uri);
- g_free (key_uri);
- key_uri = NULL;
-
- memcpy (ahs_player->cur_iv, iv, 16);
-
- g_mutex_lock (ahs_player->media_mutex);
- ahs_create_key_download_pipeline (ahs_player);
- g_cond_wait (ahs_player->key_eos_cond, ahs_player->media_mutex);
- g_mutex_unlock (ahs_player->media_mutex);
-
- g_print ("Downloaded key url.. and key data is = %s\n", ahs_player->cur_key_data);
- }
-
- ahs_player->cur_media_uri = g_strdup (media_uri);
- g_free (media_uri);
- media_uri = NULL;
-
- /* note down segment start time */
- g_get_current_time (&time);
- ahs_player->seg_start_time = (time.tv_sec * 1000000)+ time.tv_usec;
- debug_log ("start time in usec = %"G_GUINT64_FORMAT"\n", ahs_player->seg_start_time);
-
- bret = ahs_create_media_download_pipeline (ahs_player);
- if (FALSE == bret)
- {
- goto exit;
- }
-
- /* waiting for media file to be downloaded */
- g_mutex_lock (ahs_player->media_mutex);
- if (ahs_player->media_thread_exit)
- {
- g_mutex_unlock (ahs_player->media_mutex);
- goto exit;
- }
- debug_log ("waiting on media EOS....\n");
- g_cond_wait (ahs_player->media_eos_cond, ahs_player->media_mutex);
- g_mutex_unlock (ahs_player->media_mutex);
-
- debug_log ("Done with waiting on media EOS....\n");
-
- }
-
-
-exit:
- debug_log ("Exiting from media thread...\n");
- ahs_player->media_thread_exit = TRUE;
- g_thread_exit (ahs_player->media_thread);
- return NULL;
-}
-
-static gboolean
-ahs_create_manifest_download_pipeline (mm_player_ahs_t *ahs_player)
-{
- gboolean bret = FALSE;
- GstStateChangeReturn sret = GST_STATE_CHANGE_SUCCESS;
- gchar* manifest_dump_file_name = NULL;
- gint fd = -1;
-
- debug_log ("<<<\n");
-
- /* If pipeline exists, then cleanup first */
- if (ahs_player->manifest_download_pipeline)
- ahs_destory_manifest_download_pipeline(ahs_player);
-
- /* Create element */
- ahs_player->manifest_download_pipeline = gst_pipeline_new ("AHS manifest Pipeline");
- if (NULL == ahs_player->manifest_download_pipeline)
- {
- debug_error ("Can't create manifest download pipeline...");
- return FALSE;
- }
- ahs_player->manifest_download_src = gst_element_factory_make ("souphttpsrc", "AHS manifest download source");
- if (NULL == ahs_player->manifest_download_src)
- {
- debug_error ("Can't create manifest download src...");
- return FALSE;
- }
-
- if (ahs_player->user_agent)
- {
- g_object_set (ahs_player->manifest_download_src, "user-agent", ahs_player->user_agent, NULL );
- }
-
- ahs_player->manifest_download_sink = gst_element_factory_make ("filesink", "AHS manifest download sink");
- if (NULL == ahs_player->manifest_download_sink)
- {
- debug_error ("Can't create manifest download sink...");
- return FALSE;
- }
-
- /* Add to bin and link */
- gst_bin_add_many (GST_BIN (ahs_player->manifest_download_pipeline),
- ahs_player->manifest_download_src, ahs_player->manifest_download_sink,
- NULL);
-
- bret = gst_element_link (ahs_player->manifest_download_src, ahs_player->manifest_download_sink);
- if (FALSE == bret)
- {
- debug_error ("Can't link elements src and sink...");
- return FALSE;
- }
-
- /* Set Bus */
- GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (ahs_player->manifest_download_pipeline));
- gst_bus_add_watch (bus, ahs_manifest_download_callback, ahs_player);
- gst_object_unref (bus);
-
- /* Set URI */
- g_object_set (G_OBJECT (ahs_player->manifest_download_src), "location", ahs_player->cur_mf_uri, NULL);
-
- if (ahs_player->ahs_manifest_dmp_location)
- g_unlink(ahs_player->ahs_manifest_dmp_location);
-
- /* set path to dump manifest file */
- manifest_dump_file_name = g_strdup(HLS_MANIFEST_DEFAULT_FILE_NAME);
-
- fd = g_mkstemp(manifest_dump_file_name);
- if (fd == -1)
- {
- debug_error("failed to open temporary file\n");
- MMPLAYER_FREEIF(manifest_dump_file_name);
- return FALSE;
- }
-
- sprintf (ahs_player->ahs_manifest_dmp_location, "%s.m3u8", manifest_dump_file_name);
-
- if (g_file_test (manifest_dump_file_name, G_FILE_TEST_EXISTS))
- {
- close(fd);
- g_unlink(manifest_dump_file_name);
- }
-
- MMPLAYER_FREEIF(manifest_dump_file_name);
-
- /* ENAMETOOLONG or not */
- if (strlen(ahs_player->ahs_manifest_dmp_location) > HLS_POSIX_PATH_MAX)
- {
- debug_error("file name too long\n");
- return FALSE;
- }
-
- g_object_set (G_OBJECT (ahs_player->manifest_download_sink), "location", ahs_player->ahs_manifest_dmp_location, NULL);
-
- debug_log ("src location = %s, save location = %s\n", ahs_player->cur_mf_uri, ahs_player->ahs_manifest_dmp_location);
-
- g_print ("Going to download manifest-uri -> %s\n", ahs_player->cur_mf_uri);
-
- /* Start to download */
- sret = gst_element_set_state (ahs_player->manifest_download_pipeline, GST_STATE_PLAYING);
-
- debug_log ("sret = %d\n", sret);
-
- debug_log (">>>\n");
-
- return TRUE;
-
-}
-
-static gboolean
-ahs_destory_manifest_download_pipeline(mm_player_ahs_t *ahs_player)
-{
- debug_log ("<<<\n");
-
- gst_element_set_state (ahs_player->manifest_download_pipeline, GST_STATE_NULL);
- gst_element_get_state (ahs_player->manifest_download_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
-
- gst_object_unref(ahs_player->manifest_download_pipeline);
- ahs_player->manifest_download_pipeline = NULL;
-
- debug_log (">>>\n");
-
- return TRUE;
-}
-
-static gboolean
-ahs_create_media_download_pipeline (mm_player_ahs_t *ahs_player)
-{
- gboolean bret = FALSE;
- GstBus* bus = NULL;
-
- debug_log ("<<<\n");
-
- /* If pipeline exists, then cleanup first */
- if (ahs_player->media_download_pipeline)
- ahs_destory_media_download_pipeline(ahs_player);
-
- /* Create element */
- ahs_player->media_download_pipeline = gst_pipeline_new ("AHS media Pipeline");
- if (NULL == ahs_player->media_download_pipeline)
- {
- debug_error ("Can't create media download pipeline...");
- return FALSE;
- }
- ahs_player->media_download_src = gst_element_factory_make ("souphttpsrc", "AHS media download source");
- if (NULL == ahs_player->media_download_src)
- {
- debug_error ("Can't create media download src...");
- return FALSE;
- }
-
- if (ahs_player->user_agent)
- {
- g_object_set (ahs_player->media_download_src, "user-agent", ahs_player->user_agent, NULL );
- }
-
- ahs_player->media_download_sink = gst_element_factory_make ("appsink", "AHS media download sink");
- if (NULL == ahs_player->media_download_sink)
- {
- debug_error ("Can't create media download sink...");
- return FALSE;
- }
-
- /* Add to bin and link */
- gst_bin_add_many (GST_BIN (ahs_player->media_download_pipeline),
- ahs_player->media_download_src, ahs_player->media_download_sink,
- NULL);
-
- bret = gst_element_link (ahs_player->media_download_src, ahs_player->media_download_sink);
- if (FALSE == bret)
- {
- debug_error ("Can't link elements src and sink...");
- return FALSE;
- }
-
- /* Set Bus */
- bus = gst_pipeline_get_bus (GST_PIPELINE (ahs_player->media_download_pipeline));
- gst_bus_add_watch (bus, ahs_media_download_callback, ahs_player);
- gst_object_unref (bus);
-
- /* Set URI on src element */
- g_object_set (G_OBJECT (ahs_player->media_download_src), "location", ahs_player->cur_media_uri, NULL);
-
- g_print ("Going to download media-uri -> %s\n", ahs_player->cur_media_uri);
-
- /* setting properties on sink element */
- g_object_set (G_OBJECT (ahs_player->media_download_sink), "emit-signals", TRUE, "sync", FALSE, NULL);
- g_signal_connect (ahs_player->media_download_sink, "new-buffer", G_CALLBACK (on_new_buffer_from_appsink), ahs_player);
-
- /* Start to download */
- gst_element_set_state (ahs_player->media_download_pipeline, GST_STATE_PLAYING);
-
- debug_log (">>>\n");
-
- return TRUE;
-
-}
-
-static gboolean
-ahs_destory_media_download_pipeline(mm_player_ahs_t *ahs_player)
-{
- debug_log ("<<<\n");
-
- gst_element_set_state (ahs_player->media_download_pipeline, GST_STATE_NULL);
- gst_element_get_state (ahs_player->media_download_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
-
- gst_object_unref(ahs_player->media_download_pipeline);
- ahs_player->media_download_pipeline = NULL;
-
- debug_log (">>>\n");
-
- return TRUE;
-}
-
-static gboolean
-ahs_create_key_download_pipeline (mm_player_ahs_t *ahs_player)
-{
- gboolean bret = FALSE;
- GstBus* bus = NULL;
-
- debug_log ("<<<\n");
-
- /* If pipeline exists, then cleanup first */
- if (ahs_player->key_download_pipeline)
- ahs_destory_key_download_pipeline(ahs_player);
-
- /* Create element */
- ahs_player->key_download_pipeline = gst_pipeline_new ("AHS key Pipeline");
- if (NULL == ahs_player->key_download_pipeline)
- {
- debug_error ("Can't create key download pipeline...");
- return FALSE;
- }
- ahs_player->key_download_src = gst_element_factory_make ("souphttpsrc", "AHS key download source");
- if (NULL == ahs_player->key_download_src)
- {
- debug_error ("Can't create key download src...");
- return FALSE;
- }
-
- if (ahs_player->user_agent)
- {
- g_object_set (ahs_player->key_download_src, "user-agent", ahs_player->user_agent, NULL );
- }
-
- ahs_player->key_download_sink = gst_element_factory_make ("filesink", "AHS key download sink");
- if (NULL == ahs_player->key_download_sink)
- {
- debug_error ("Can't create key download sink...");
- return FALSE;
- }
-
- /* Add to bin and link */
- gst_bin_add_many (GST_BIN (ahs_player->key_download_pipeline),
- ahs_player->key_download_src, ahs_player->key_download_sink,
- NULL);
-
- bret = gst_element_link (ahs_player->key_download_src, ahs_player->key_download_sink);
- if (FALSE == bret)
- {
- debug_error ("Can't link elements src and sink...");
- return FALSE;
- }
-
- /* Set Bus */
- bus = gst_pipeline_get_bus (GST_PIPELINE (ahs_player->key_download_pipeline));
- gst_bus_add_watch (bus, ahs_key_download_callback, ahs_player);
- gst_object_unref (bus);
-
- /* Set URI */
- g_object_set (G_OBJECT (ahs_player->key_download_src), "location", ahs_player->cur_key_uri, NULL);
- sprintf (ahs_player->ahs_key_dmp_location, "/opt/apps/com.samsung.video-player/data%s", strrchr(ahs_player->cur_key_uri, '/'));
- debug_log ("src location = %s, save location = %s\n", ahs_player->cur_key_uri, ahs_player->ahs_key_dmp_location);
-
- g_print ("Going to download key-uri -> %s\n", ahs_player->cur_key_uri);
-
- g_object_set (G_OBJECT (ahs_player->key_download_sink), "location", ahs_player->ahs_key_dmp_location, NULL);
-
- /* Start to download */
- gst_element_set_state (ahs_player->key_download_pipeline, GST_STATE_PLAYING);
-
- debug_log (">>>\n");
-
- return TRUE;
-
-}
-
-static gboolean
-ahs_destory_key_download_pipeline(mm_player_ahs_t *ahs_player)
-{
- debug_log ("<<<\n");
-
- gst_element_set_state (ahs_player->key_download_pipeline, GST_STATE_NULL);
- gst_element_get_state (ahs_player->key_download_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
-
- gst_object_unref(ahs_player->key_download_pipeline);
- ahs_player->key_download_pipeline = NULL;
-
- debug_log (">>>\n");
-
- return TRUE;
-}
-static gboolean
-ahs_client_is_live (mm_player_ahs_t *ahs_player)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return (hls_client_is_live(ahs_player->ahs_client));
- }
- return TRUE;
-}
-
-static gboolean
-ahs_manifest_get_update_interval (mm_player_ahs_t *ahs_player, GTimeVal *next_update)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return hls_playlist_update_interval(ahs_player->ahs_client, next_update);
- }
- return TRUE;
-}
-
-static gboolean
-ahs_parse_manifest_update_client (mm_player_ahs_t *ahs_player)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return hls_parse_playlist_update_client(ahs_player->ahs_client, ahs_player->ahs_manifest_dmp_location);
- }
- else
- {
- return FALSE;
- }
-}
-
-static gboolean
-ahs_manifest_download_callback(GstBus *bus, GstMessage *msg, gpointer data)
-{
- mm_player_ahs_t *ahs_player = (mm_player_ahs_t*) data;
- gboolean bret = TRUE;
-
- debug_log ("<<<\n");
-
- if ( !ahs_player )
- {
- debug_error("AHS player handle is invalid\n");
- return FALSE;
- }
-
- switch ( GST_MESSAGE_TYPE( msg ) )
- {
- case GST_MESSAGE_EOS:
- {
- debug_log("MANIFEST EOS received, state=[%d]\n", ahs_player->ahs_state);
-
- if (ahs_player->manifest_download_pipeline)
- ahs_destory_manifest_download_pipeline(ahs_player);
-
- /* Parse and Update client*/
- ahs_parse_manifest_update_client (ahs_player);
-
- debug_log ("Current STATE = [%s]\n", state_string[ahs_player->ahs_state]);
-
- debug_log ("Received EOS on manifest download...broadcast manifest eos\n");
- g_cond_broadcast (ahs_player->manifest_eos_cond);
-
- /* state transition : MAIN PLAYLIST -> SUB PLAYLIST (optional) -> MEDIA FILE STREAMING */
- g_mutex_lock (ahs_player->state_lock);
- if (ahs_player->ahs_state == AHS_STATE_PREPARE_MANIFEST)
- {
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- ////////////////////////////////
- //// http live streaming
- ///////////////////////////////
-
- if (hls_downloaded_variant_playlist (ahs_player->ahs_client, ahs_player->cur_mf_uri))
- {
- debug_log ("Downloaded Variant playlist file\n");
- /* if set current playlist based on bandwidth */
- ahs_set_current_manifest (ahs_player);
-
- if (ahs_player->cur_mf_uri)
- {
- g_free (ahs_player->cur_mf_uri);
- ahs_player->cur_mf_uri = NULL;
- }
-
- ahs_player->cur_mf_uri = g_strdup(ahs_get_current_manifest(ahs_player));
-
- debug_log ("Signal to wakeup manifest thread...\n");
- g_cond_signal (ahs_player->manifest_update_cond);
- }
- else
- {
- ahs_player->ahs_state = AHS_STATE_MEDIA_STREAMING;
- }
- }
- }
-
- /* If state is for media streaming */
- debug_log ("Current STATE = [%s]\n", state_string[ahs_player->ahs_state]);
-
- if (AHS_STATE_MEDIA_STREAMING == ahs_player->ahs_state)
- {
- debug_log ("Signal start of media download....\n");
- g_cond_signal (ahs_player->media_start_cond);
- }
- g_mutex_unlock (ahs_player->state_lock);
- }
-
- break;
-
- case GST_MESSAGE_ERROR:
- {
- gboolean ret = FALSE;
- GError *error = NULL;
- gchar* debug = NULL;
- GstMessage *new_msg = NULL;
-
- /* get error code */
- gst_message_parse_error( msg, &error, &debug );
- debug_error ("GST_MESSAGE_ERROR = %s\n", debug);
- new_msg = gst_message_new_error (GST_OBJECT_CAST ((GstAppSrc *)ahs_player->appsrc), error, debug);
-
- ret = gst_element_post_message ((GstAppSrc *)ahs_player->appsrc, new_msg);
- __mm_player_ahs_stop (ahs_player);
- //__mm_player_ahs_deinitialize(ahs_player);
- //__mm_player_ahs_destroy(&ahs_player);
-
- g_print ("\n\n\nError posting msg = %d\n\n\n\n", ret);
- //g_free( debug);
- //debug = NULL;
- //g_error_free( error);
- }
- break;
-
- case GST_MESSAGE_WARNING:
- {
- char* debug = NULL;
- GError* error = NULL;
- gst_message_parse_warning(msg, &error, &debug);
- debug_warning("warning : %s\n", error->message);
- debug_warning("debug : %s\n", debug);
- g_free( debug);
- debug = NULL;
- g_error_free( error);
- }
- break;
-
- default:
- //debug_warning("unhandled message\n");
- break;
- }
-
- debug_log (">>>\n");
-
- return bret;
-}
-
-static gboolean
-ahs_key_download_callback(GstBus *bus, GstMessage *msg, gpointer data)
-{
- mm_player_ahs_t *ahs_player = (mm_player_ahs_t*) data;
- gboolean bret = TRUE;
-
- debug_log ("<<<\n");
-
- if ( !ahs_player )
- {
- debug_error("AHS player handle is invalid\n");
- return FALSE;
- }
-
- switch ( GST_MESSAGE_TYPE( msg ) )
- {
- case GST_MESSAGE_EOS:
- {
- FILE *keyfd = NULL;
- guint bytes_read = 0;
- int i =0;
-
- debug_log("KEY EOS received, state=[%d]\n", ahs_player->ahs_state);
- if (ahs_player->key_download_pipeline)
- ahs_destory_key_download_pipeline(ahs_player);
-
- debug_log ("Current STATE = [%s]\n", state_string[ahs_player->ahs_state]);
-
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- keyfd = fopen (ahs_player->ahs_key_dmp_location, "r");
- if (keyfd == NULL)
- {
- g_print ("failed to open key file...\n\n\n");
- return FALSE;
- }
-
- /* read key file */
- bytes_read = fread (ahs_player->cur_key_data, sizeof (unsigned char), 16, keyfd);
- if (sizeof(ahs_player->cur_key_data) != bytes_read)
- {
- printf ("key file is not proper...bytes_read from key file = %d\n", bytes_read);
- return FALSE;
- }
-
- bret = hls_decryption_initialize (ahs_player->ahs_client, &ahs_player->cur_key_data, ahs_player->cur_iv);
- if (FALSE == bret)
- {
- g_print ("Failed to initialize encryption....\n\n");
- }
- }
- g_cond_signal (ahs_player->key_eos_cond);
- debug_log ("signalling key download EOS\n");
- }
-
- break;
-
- case GST_MESSAGE_ERROR:
- {
- GError *error = NULL;
- gchar* debug = NULL;
- /* get error code */
- //gst_message_parse_error( msg, &error, &debug );
- debug_error ("GST_MESSAGE_ERROR = %s\n", debug);
-
- gst_element_post_message ((GstAppSrc *)ahs_player->appsrc, msg);
- //g_free( debug);
- debug = NULL;
- //g_error_free( error);
- }
- break;
-
- case GST_MESSAGE_WARNING:
- {
- char* debug = NULL;
- GError* error = NULL;
- gst_message_parse_warning(msg, &error, &debug);
- debug_warning("warning : %s\n", error->message);
- debug_warning("debug : %s\n", debug);
- g_free( debug);
- debug = NULL;
- g_error_free( error);
- }
- break;
-
- default:
- //debug_warning("unhandled message\n");
- break;
- }
- return bret;
-}
-
-
-static gboolean
-ahs_media_download_callback(GstBus *bus, GstMessage *msg, gpointer data)
-{
- mm_player_ahs_t *ahs_player = (mm_player_ahs_t*) data;
- gboolean bret = TRUE;
-
- debug_log ("<<<\n");
-
- if ( !ahs_player )
- {
- debug_error("AHS player handle is invalid\n");
- return FALSE;
- }
-
- switch ( GST_MESSAGE_TYPE( msg ) )
- {
- case GST_MESSAGE_EOS:
- {
- glong diff = 0;
- GTimeVal time = {0, };
-
- debug_log("MEDIA EOS received, state=[%d]\n", ahs_player->ahs_state);
-
- if (ahs_player->media_download_pipeline)
- ahs_destory_media_download_pipeline(ahs_player);
-
- g_get_current_time (&time);
- ahs_player->seg_end_time = (time.tv_sec * 1000000)+ time.tv_usec;
- debug_log ("end time in usec = %"G_GUINT64_FORMAT"\n", ahs_player->seg_end_time);
-
- diff = ahs_player->seg_end_time - ahs_player->seg_start_time;
-
- ahs_player->download_rate = (guint)((ahs_player->seg_size * 8 * 1000000) / diff);
-
- ahs_player->cache_frag_count++;
-
-
- g_print("*********** frag_cnt = %d and download rate = %d bps **************\n", ahs_player->cache_frag_count, ahs_player->download_rate);
-
- /* first initial fragments go with least possible bit-rate */
- if (ahs_player->cache_frag_count == DEFAULT_FRAGMENTS_CACHE)
- {
- debug_log ("=======================================\n");
- debug_log (" \t Done with caching initial %d fragments\n", ahs_player->cache_frag_count);
- debug_log ("=======================================\n");
- }
-
- if (ahs_player->cache_frag_count >= DEFAULT_FRAGMENTS_CACHE)
- {
- ahs_switch_playlist (ahs_player, ahs_player->download_rate);
- }
-
- ahs_player->seg_size = 0;
-
- g_mutex_lock (ahs_player->media_mutex);
- g_cond_broadcast (ahs_player->media_eos_cond);
- g_mutex_unlock (ahs_player->media_mutex);
-
- debug_log ("Signaled media ts EOS...\n");
-
- }
- break;
-
- case GST_MESSAGE_ERROR:
- {
- GError *error = NULL;
- gchar* debug = NULL;
- GstMessage *new_msg = NULL;
- gboolean ret = FALSE;
-
- /* get error code */
- gst_message_parse_error( msg, &error, &debug );
- debug_error ("GST_MESSAGE_ERROR = %s\n", debug);
- new_msg = gst_message_new_error (GST_OBJECT_CAST ((GstAppSrc *)ahs_player->appsrc), error, debug);
-
- ret = gst_element_post_message ((GstAppSrc *)ahs_player->appsrc, new_msg);
-
- //MMPLAYER_FREEIF( debug );
- //g_error_free( error );
- }
- break;
-
- case GST_MESSAGE_WARNING:
- {
- char* debug = NULL;
- GError* error = NULL;
- gst_message_parse_warning(msg, &error, &debug);
- debug_warning("warning : %s\n", error->message);
- debug_warning("debug : %s\n", debug);
- MMPLAYER_FREEIF( debug );
- g_error_free( error );
- }
- break;
-
- default:
- //debug_warning("unhandled message\n");
- break;
- }
- //debug_log (">>>\n");
- return bret;
-}
-
-static gboolean
-ahs_determining_next_file_load (mm_player_ahs_t *ahs_player, gboolean *is_ready)
-{
- debug_log ("<<<\n");
- gboolean bret = TRUE;
-
- if (ahs_player->ahs_state == AHS_STATE_PREPARE_MANIFEST)
- {
- debug_log ("STATE is not ready to download next file");
- return FALSE;
- }
-
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- bret = hls_determining_next_file_load (ahs_player->ahs_client, is_ready);
- }
-
- debug_log (">>>\n");
- return bret;
-}
-
-
-static gboolean
-ahs_set_current_manifest (mm_player_ahs_t *ahs_player)
-{
- gboolean bret = TRUE;
-
- bret = hls_set_current_playlist (ahs_player->ahs_client);
- if (FALSE == bret)
- {
- debug_error ("ERROR in setting current playlist....");
- return FALSE;
- }
-
- return bret;
-}
-
-static gchar*
-ahs_get_current_manifest (mm_player_ahs_t *ahs_player)
-{
- return hls_get_current_playlist (ahs_player->ahs_client);
-}
-
-static gboolean
-ahs_switch_playlist (mm_player_ahs_t *ahs_player, guint download_rate)
-{
- if ((MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type) && (hls_can_switch (ahs_player->ahs_client)))
- {
- ahs_player->need_bw_switch = FALSE;
-
- hls_switch_playlist (ahs_player->ahs_client, download_rate, &ahs_player->need_bw_switch);
-
- debug_log ("Need BW Switch = %d\n", ahs_player->need_bw_switch);
-
- if (ahs_player->cur_mf_uri)
- {
- g_free (ahs_player->cur_mf_uri);
- ahs_player->cur_mf_uri = NULL;
- }
-
- ahs_player->cur_mf_uri = g_strdup(ahs_get_current_manifest(ahs_player));
-
- /* Start downloading sub playlist */
-
- g_mutex_lock (ahs_player->state_lock);
- ahs_player->ahs_state = AHS_STATE_PREPARE_MANIFEST;
- g_mutex_unlock (ahs_player->state_lock);
-
- }
-
- return TRUE;
-
-}
-
-static gboolean
-ahs_get_next_media_uri (mm_player_ahs_t *ahs_player, gchar **media_uri, gchar **key_uri, char **iv)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return hls_get_next_media_fragment (ahs_player->ahs_client, media_uri, key_uri, iv);
- }
-
- return TRUE;
-}
-
-static gboolean
-ahs_is_buffer_discontinuous (mm_player_ahs_t *ahs_player)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return hls_is_buffer_discontinuous (ahs_player->ahs_client);
- }
- else
- {
- return FALSE;
- }
-}
-
-
-static gboolean
-ahs_clear_discontinuous (mm_player_ahs_t *ahs_player)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return hls_clear_discontinuous (ahs_player->ahs_client);
- }
- else
- {
- return FALSE;
- }
-}
-
-static gboolean
-ahs_decrypt_media (mm_player_ahs_t *ahs_player,GstBuffer *InBuf, GstBuffer **OutBuf)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return hls_decrypt_media_fragment (ahs_player->ahs_client, InBuf, OutBuf);
- }
-
- return TRUE;
-}
-
-gboolean
-ahs_check_allow_cache (mm_player_ahs_t *ahs_player)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return hls_check_allow_cache (ahs_player->ahs_client);
- }
- return FALSE;
-}
-
-gboolean
-ahs_store_media_presentation (mm_player_ahs_t *ahs_player, unsigned char *buffer, unsigned int buffer_len)
-{
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- return hls_store_media_presentation (ahs_player->ahs_client, buffer, buffer_len);
- }
-}
-
-mm_player_ahs_t * __mm_player_ahs_create ()
-{
- g_print ("\n >>>>>>>>>>>CREATE AHS download\n");
-
- mm_player_ahs_t *ahs_player = NULL;
-
- ahs_player = (mm_player_ahs_t *) malloc (sizeof (mm_player_ahs_t));
- if (NULL == ahs_player)
- {
- debug_error ("Failed to created ahs_player handle...\n");
- goto ERROR;
- }
-
- ahs_player->manifest_mutex = g_mutex_new ();
- if (NULL == ahs_player->manifest_mutex)
- {
- goto ERROR;
- }
- ahs_player->manifest_eos_cond = g_cond_new ();
- if (NULL == ahs_player->manifest_eos_cond)
- {
- goto ERROR;
- }
- ahs_player->manifest_exit_cond = g_cond_new ();
- if (NULL == ahs_player->manifest_exit_cond)
- {
- goto ERROR;
- }
- ahs_player->manifest_update_cond = g_cond_new ();
- if (NULL == ahs_player->manifest_update_cond)
- {
- goto ERROR;
- }
- ahs_player->media_mutex = g_mutex_new ();
- if (NULL == ahs_player->media_mutex)
- {
- goto ERROR;
- }
- ahs_player->media_start_cond = g_cond_new ();
- if (NULL == ahs_player->media_start_cond)
- {
- goto ERROR;
- }
- ahs_player->media_eos_cond = g_cond_new ();
- if (NULL == ahs_player->media_eos_cond)
- {
- goto ERROR;
- }
- ahs_player->key_eos_cond = g_cond_new ();
- if (NULL == ahs_player->key_eos_cond)
- {
- goto ERROR;
- }
- ahs_player->state_lock = g_mutex_new ();
- if (NULL == ahs_player->state_lock)
- {
- goto ERROR;
- }
-
- ahs_player->uri_type = MM_PLAYER_URI_TYPE_NONE;
- ahs_player->is_initialized = FALSE;
- ahs_player->main_mf_uri = NULL;
- ahs_player->cur_mf_uri = NULL;
- ahs_player->cur_media_uri = NULL;
- ahs_player->appsrc = NULL;
- ahs_player->manifest_thread = NULL;
- ahs_player->media_thread = NULL;
- /* manifest related variables */
- ahs_player->manifest_thread = NULL;
- ahs_player->manifest_thread_exit = FALSE;
- ahs_player->manifest_download_pipeline = NULL;
- ahs_player->manifest_download_src = NULL;
- ahs_player->manifest_download_sink = NULL;
-
- memset (ahs_player->ahs_manifest_dmp_location, 0, HLS_POSIX_PATH_MAX);
-
- /* media related variables */
- ahs_player->media_thread = NULL;
- ahs_player->media_thread_exit = FALSE;
-
- ahs_player->media_download_pipeline = NULL;
- ahs_player->media_download_src = NULL;
- ahs_player->media_download_sink = NULL;
-
- /* key related variables */
- ahs_player->cur_key_uri = NULL;
- memset (ahs_player->ahs_key_dmp_location, 0, 256);
- ahs_player->key_download_pipeline = NULL;
- ahs_player->key_download_src = NULL;
- ahs_player->key_download_sink = NULL;
-
- ahs_player->seg_start_time = 0; /* segment start time in usec*/
- ahs_player->seg_end_time = 0;
- ahs_player->seg_size = 0;
- ahs_player->cache_frag_count = 0;
-
- ahs_player->hls_is_wait_for_reload = FALSE;
-
- g_print ("\n >>>>>>>>>>>CREATE AHS download DONE\n");
-
- return ahs_player;
-
-ERROR:
- MMPLAYER_FREEIF(ahs_player);
-
- if (ahs_player->manifest_mutex)
- g_mutex_free(ahs_player->manifest_mutex);
-
- if ( ahs_player->manifest_eos_cond )
- g_cond_free ( ahs_player->manifest_eos_cond );
-
- if ( ahs_player->manifest_exit_cond )
- g_cond_free ( ahs_player->manifest_exit_cond );
-
- if ( ahs_player->manifest_update_cond )
- g_cond_free ( ahs_player->manifest_update_cond );
-
- if (ahs_player->media_mutex)
- g_mutex_free(ahs_player->media_mutex);
-
- if ( ahs_player->media_start_cond )
- g_cond_free ( ahs_player->media_start_cond );
-
- if ( ahs_player->media_eos_cond )
- g_cond_free ( ahs_player->media_eos_cond );
-
- if ( ahs_player->key_eos_cond )
- g_cond_free ( ahs_player->key_eos_cond );
-
- if (ahs_player->state_lock)
- g_mutex_free(ahs_player->state_lock);
-
- return NULL;
-
-
-}
-
-gboolean __mm_player_ahs_initialize (mm_player_ahs_t *ahs_player, int uri_type, char *uri, GstElement *appsrc)
-{
- gchar *system_ua = NULL;
-
- debug_log ("<<<\n");
-
- if (NULL == ahs_player)
- {
- debug_error (" Invalid argument\n");
- return FALSE;
- }
-
- g_print ("\n\n Initialize \n\n");
-
- ahs_player->user_agent = NULL;
-
- system_ua = (char *)(vconf_get_str(VCONFKEY_ADMIN_UAGENT));
-
- if (system_ua)
- {
- ahs_player->user_agent = g_strdup(system_ua);
- debug_log ("hls user-agent = %s\n", ahs_player->user_agent);
- }
-
- /* initialize ahs common variables */
- ahs_player->uri_type = uri_type;
- ahs_player->main_mf_uri = g_strdup (uri);
- ahs_player->cur_mf_uri = g_strdup (uri);
- ahs_player->appsrc = appsrc;
- ahs_player->ahs_state = AHS_STATE_STOP;
- ahs_player->need_bw_switch = FALSE;
-
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- /* http live streaming */
- ahs_player->ahs_client = __mm_player_hls_create ();
- if (NULL == ahs_player->ahs_client)
- {
- return FALSE;
- }
- __mm_player_hls_initialize (ahs_player->ahs_client, ahs_player->main_mf_uri);
- }
-
- debug_log (">>>\n");
-
- ahs_player->is_initialized = TRUE;
-
- return TRUE;
-}
-
-gboolean __mm_player_ahs_start (mm_player_ahs_t *ahs_player)
-{
- gboolean bret = TRUE;
-
- debug_log ("<<<\n");
-
- if (NULL == ahs_player)
- {
- debug_error (" Invalid argument\n");
- return FALSE;
- }
-
- g_print ("\n >>>>>>>>>>> AHS download START\n");
-
- /* download manifest file */
- if (!ahs_create_manifest_download_pipeline (ahs_player))
- return FALSE;
-
- ahs_player->ahs_state = AHS_STATE_PREPARE_MANIFEST;
-
- ahs_player->manifest_thread = g_thread_create (manifest_update_thread, (gpointer)ahs_player, TRUE, NULL);
-
- if ( !ahs_player->manifest_thread )
- {
- debug_error("failed to create thread : manifest\n");
- goto ERROR;
- }
-
- /* media download thread */
- ahs_player->media_thread = g_thread_create (media_download_thread, (gpointer)ahs_player, TRUE, NULL);
-
- if ( !ahs_player->media_thread )
- {
- debug_error("failed to create thread : media\n");
- goto ERROR;
- }
-
- g_print ("\n >>>>>>>>>>> AHS download START DONE\n");
-
- debug_log (">>>\n");
-
- return bret;
-
-ERROR:
-
- if (ahs_player->manifest_thread)
- {
- g_thread_join( ahs_player->manifest_thread);
- ahs_player->manifest_thread = NULL;
- }
-
- if (ahs_player->media_thread)
- {
- g_thread_join( ahs_player->media_thread);
- ahs_player->media_thread = NULL;
- }
-
- return FALSE;
-}
-
-gboolean __mm_player_ahs_pause (mm_player_ahs_t *ahs_player)
-{
- gboolean bret = TRUE;
-
- debug_log ("<<<\n");
-
- if (NULL == ahs_player)
- {
- debug_error (" Invalid argument\n");
- return FALSE;
- }
-
- g_print ("\n\n\n PAUSED \n\n\n");
-
- g_mutex_lock (ahs_player->state_lock);
- if (AHS_STATE_MEDIA_STREAMING != ahs_player->ahs_state)
- {
- g_print ("Pipeline is not in playing state...\n");
- g_mutex_unlock (ahs_player->state_lock);
- return TRUE;
- }
- g_mutex_unlock (ahs_player->state_lock);
-
- if (ahs_client_is_live (ahs_player))
- {
- g_print ("Live playlist flush now");
- }
-
- return bret;
-
-}
-
-gboolean __mm_player_ahs_deinitialize (mm_player_ahs_t *ahs_player)
-{
- debug_log ("<<<\n");
-
- g_print ("\n >>>>>>>>>>> AHS deinitalize \n");
-
- if (NULL == ahs_player)
- {
- debug_error (" Invalid argument\n");
- return FALSE;
- }
-
- if (FALSE == ahs_player->is_initialized)
- {
- debug_log ("already de-initlialized\n");
- g_print ("\n\n######## already de-initlialized\n");
-
- return TRUE;
- }
-
- ahs_player->need_bw_switch = FALSE;
- ahs_player->hls_is_wait_for_reload= FALSE;
-
- ahs_player->appsrc = NULL;
-
- if (MM_PLAYER_URI_TYPE_HLS == ahs_player->uri_type)
- {
- if (ahs_player->ahs_client)
- {
- __mm_player_hls_destroy (ahs_player->ahs_client);
- ahs_player->ahs_client = NULL;
- }
- }
-
- /* manifest related variables */
- ahs_player->manifest_thread = NULL;
- ahs_player->manifest_thread_exit = TRUE;
- ahs_player->uri_type = MM_PLAYER_URI_TYPE_NONE;
-
-
- /* media related variables */
- ahs_player->media_thread = NULL;
- ahs_player->media_thread_exit = TRUE;
-
-
- ahs_player->is_initialized = FALSE;
-
- if (ahs_player->ahs_manifest_dmp_location)
- g_unlink(ahs_player->ahs_manifest_dmp_location);
-
- g_print ("\n >>>>>>>>>>> AHS deinitalize DONE \n");
- debug_log (">>>\n");
-
- return TRUE;
-}
-
-gboolean __mm_player_ahs_stop (mm_player_ahs_t *ahs_player)
-{
- GstFlowReturn fret = GST_FLOW_OK;
-
- debug_fenter ();
-
- if (NULL == ahs_player)
- {
- debug_error ("Invalid argument...\n");
- return FALSE;
- }
-
- if (ahs_player->ahs_state == AHS_STATE_STOP)
- {
- debug_log ("Already in AHS STOP state...\n");
- return TRUE;
- }
-
- if (ahs_player->appsrc)
- {
- debug_log ("Push EOS to playback pipeline\n");
- // TODO: try to send FLUSH event instead of EOS
- fret = gst_app_src_end_of_stream ((GstAppSrc *)ahs_player->appsrc);
- if (fret != GST_FLOW_OK)
- {
- debug_error ("Error in pushing EOS to appsrc: reason - %s\n", gst_flow_get_name(fret));
- }
- }
-
- ahs_player->ahs_state = AHS_STATE_STOP;
-
- if (ahs_player->media_thread)
- {
- g_mutex_lock (ahs_player->media_mutex);
- ahs_player->media_thread_exit = TRUE;
- g_mutex_unlock (ahs_player->media_mutex);
-
- g_cond_broadcast (ahs_player->manifest_eos_cond);
- g_cond_broadcast (ahs_player->media_eos_cond);
- g_cond_broadcast (ahs_player->media_start_cond);
- g_cond_broadcast (ahs_player->key_eos_cond);
-
- debug_log ("waiting for media thread to finish\n");
- g_thread_join (ahs_player->media_thread);
- ahs_player->media_thread = NULL;
- debug_log("media thread released\n");
- }
-
- if (ahs_player->manifest_thread)
- {
- g_mutex_lock (ahs_player->manifest_mutex);
- ahs_player->manifest_thread_exit = TRUE;
- g_mutex_unlock (ahs_player->manifest_mutex);
-
- g_cond_broadcast (ahs_player->manifest_update_cond);
- g_cond_broadcast (ahs_player->manifest_eos_cond);
-
- debug_log ("waiting for manifest thread to finish\n");
- g_thread_join (ahs_player->manifest_thread);
- ahs_player->manifest_thread = NULL;
- debug_log("manifest thread released\n");
- }
-
- if (ahs_player->manifest_download_pipeline)
- ahs_destory_manifest_download_pipeline(ahs_player);
-
- if (ahs_player->media_download_pipeline)
- ahs_destory_media_download_pipeline(ahs_player);
-
- if (ahs_player->key_download_pipeline)
- ahs_destory_key_download_pipeline(ahs_player);
-
- debug_fleave ();
-
- return TRUE;
-
-}
-
-gboolean __mm_player_ahs_destroy (mm_player_ahs_t *ahs_player)
-{
- g_print ("\n >>>>>>>>>>>Destroying AHS download\n");
- debug_log ("<<<<<\n");
-
- if (NULL == ahs_player)
- {
- debug_error ("Invalid argument...\n");
- g_print ("Invalid argument...\n");
- return TRUE;
- }
-
- debug_log ("\nBroadcasting signals from destory\n\n\n");
-
- if (ahs_player->manifest_update_cond)
- g_cond_broadcast (ahs_player->manifest_update_cond);
-
- if (ahs_player->manifest_eos_cond)
- g_cond_broadcast (ahs_player->manifest_eos_cond);
-
- if (ahs_player->media_eos_cond)
- g_cond_broadcast (ahs_player->media_eos_cond);
-
- if (ahs_player->media_start_cond)
- g_cond_broadcast (ahs_player->media_start_cond);
-
- if (ahs_player->key_eos_cond)
- g_cond_broadcast (ahs_player->key_eos_cond);
-
-
- g_print ("waiting for manifest thread to finish from destroy\n");
- if (ahs_player->manifest_thread)
- {
- g_thread_join (ahs_player->manifest_thread);
- }
- g_print ("waiting for media thread to finish from destroy\n");
-
- if (ahs_player->media_thread)
- {
- g_thread_join (ahs_player->media_thread);
- }
- g_print ("DESTROY threads are DEAD \n");
-
- /* initialize ahs common variables */
- if (ahs_player->main_mf_uri)
- {
- g_free (ahs_player->main_mf_uri);
- ahs_player->main_mf_uri = NULL;
- }
-
- if (ahs_player->cur_mf_uri)
- {
- g_free (ahs_player->cur_mf_uri);
- ahs_player->cur_mf_uri = NULL;
- }
-
- if (ahs_player->cur_media_uri)
- {
- g_free (ahs_player->cur_media_uri);
- ahs_player->cur_media_uri = NULL;
- }
- if (ahs_player->manifest_mutex)
- {
- g_mutex_free (ahs_player->manifest_mutex);
- ahs_player->manifest_mutex = NULL;
- }
- if (ahs_player->manifest_eos_cond)
- {
- g_cond_free (ahs_player->manifest_eos_cond);
- ahs_player->manifest_eos_cond = NULL;
- }
- if (ahs_player->manifest_exit_cond)
- {
- g_cond_free (ahs_player->manifest_exit_cond);
- ahs_player->manifest_exit_cond = NULL;
- }
- if (ahs_player->manifest_update_cond)
- {
- g_cond_free (ahs_player->manifest_update_cond);
- ahs_player->manifest_update_cond = NULL;
- }
- if (ahs_player->media_mutex)
- {
- g_mutex_free (ahs_player->media_mutex);
- ahs_player->media_mutex = NULL;
- }
- if (ahs_player->media_eos_cond)
- {
- g_cond_free (ahs_player->media_eos_cond);
- ahs_player->media_eos_cond = NULL;
- }
- if (ahs_player->media_start_cond)
- {
- g_cond_free (ahs_player->media_start_cond);
- ahs_player->media_start_cond = NULL;
- }
-
- /* key related variables */
- if (ahs_player->key_eos_cond)
- {
- g_cond_free (ahs_player->key_eos_cond);
- ahs_player->key_eos_cond = NULL;
- }
- if (ahs_player->cur_key_uri )
- {
- g_free (ahs_player->cur_key_uri);
- ahs_player->cur_key_uri = NULL;
- }
-
- if (ahs_player->ahs_client)
- {
- __mm_player_hls_destroy(ahs_player->ahs_client);
- ahs_player->ahs_client = NULL;
- }
-
- MMPLAYER_FREEIF(ahs_player->user_agent);
-
- free (ahs_player);
- ahs_player = NULL;
-
- g_print ("\n >>>>>>>>>>>Destroying AHS download DONE\n");
-
- debug_log (">>>>>\n");
-
- return TRUE;
-
-}
-
-
+++ /dev/null
-/*
- * libmm-player
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
- * YoungHwan An <younghwan_.an@samsung.com>, naveen cherukuri <naveen.ch@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "mm_player_ahs_hls.h"
-
-static const float update_interval_factor[] = { 1, 0.5, 1.5, 3 };
-#define AES_BLOCK_SIZE 16
-#define BITRATE_SWITCH_UPPER_THRESHOLD 0.4
-#define BITRATE_SWITCH_LOWER_THRESHOLD 0.1
-
-static gboolean hls_switch_to_lowerband (mm_player_hls_t * player, guint download_rate);
-static gboolean hls_switch_to_upperband (mm_player_hls_t * ahs_player, GList *next_bw_lists, guint download_rate);
-
-/* utility function for removing '\r' character in string */
-char* string_replace (char* text, int len)
-{
- int i=0;
- char *dst_ptr = NULL;
- char* tmp = malloc (len);
- if (NULL == tmp)
- {
- debug_error ("Failed to allocate memory...\n");
- return NULL;
- }
- memset (tmp, 0, len);
- dst_ptr = tmp;
-
- for (i=0; i<len; i++) {
- if (text[i] != '\r') {
- *dst_ptr++ = text[i];
- }
- }
- return tmp;
-}
-
-gint my_compare (gconstpointer a, gconstpointer b)
-{
- int first = ((GstM3U8*)a)->bandwidth;
- int second = ((GstM3U8*)b)->bandwidth;
- //return second - first;
- return first - second; // ascending sort
-}
-
-void hls_dump_mediafile (GstM3U8MediaFile* mediafile)
-{
- debug_log ("[%d][%d][%s][%s]\n", mediafile->sequence, mediafile->duration, mediafile->title, mediafile->uri);
-}
-
-void hls_dump_m3u8 (GstM3U8* m3u8)
-{
- debug_log ("uri = [%s]\n", m3u8->uri);
- debug_log ("version = [%d], endlist = [%d], bandwidth = [%d], target duration = [%d], mediasequence = [%d]\n",
- m3u8->version, m3u8->endlist, m3u8->bandwidth, m3u8->targetduration, m3u8->mediasequence);
- debug_log ("allow cache = %s, program_id = %d, codecs = %s\n", m3u8->allowcache, m3u8->program_id, m3u8->codecs);
- debug_log ("width = %d, height = %d\n", m3u8->width, m3u8->height);
- debug_log ("last data = [%s], parent = [%p]\n", m3u8->last_data, m3u8->parent);
-
- GList* tmp = m3u8->lists;
- while (tmp) {
- debug_log ("################### SUB playlist ##################\n");
- hls_dump_m3u8 (tmp->data);
- tmp = g_list_next(tmp);
- }
-
- tmp = m3u8->files;
- while (tmp) {
- hls_dump_mediafile (tmp->data);
- tmp = g_list_next(tmp);
- }
-}
-
-void hls_dump_playlist (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- debug_log ("============================== DUMP PLAYLIST =================================\n");
- debug_log ("update_failed_count = %d, seq = %d\n", hls_player->client->update_failed_count, hls_player->client->sequence);
-
- if (hls_player->client->current)
- {
- debug_log ("################### CURRENT playlist ##################\n");
- hls_dump_m3u8 (hls_player->client->current);
- }
- debug_log ("================================ E N D =================================\n");
-}
-
-#define MMPLAYER_DEFAULT_AUDIO_BANDWIDTH 70000 /* FIXIT */
-
-gboolean hls_parse_playlist_update_client (void *hls_handle, char* playlist)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
- GError *error = NULL;
- guint8 *data = NULL;
-
- debug_log ("<<< Playlist = [%s] \n" ,playlist);
-
- /* prepare MMAP */
- GMappedFile *file = g_mapped_file_new (playlist, TRUE, &error);
- if (error)
- {
- g_print ("failed to open file: %s\n", error->message);
- g_error_free (error);
- return FALSE;
- }
-
- data = (guint8 *) g_mapped_file_get_contents (file);
-
- /* Get replaced text (remove '\r') */
- char* replaced_text = string_replace (data, g_mapped_file_get_length (file));
-
- /* update with replaced text */
- if (gst_m3u8_client_update (hls_player->client, replaced_text))
- {
- GList *my_list = NULL;
- guint list_count = g_list_length(hls_player->client->main->lists);
-
- debug_log("sublist count = %d\n", list_count);
-
- if (list_count > 1)
- {
- for (my_list = hls_player->client->main->lists; my_list != NULL; my_list = g_list_next (my_list))
- {
- GstM3U8 *my_m3u8 = NULL;
-
- my_m3u8 = (GstM3U8 *)my_list->data;
-
- /* check if it can be audio or not */
- if (my_m3u8->bandwidth < MMPLAYER_DEFAULT_AUDIO_BANDWIDTH)
- {
- /* doesn't consider it */
- hls_player->client->main->lists = g_list_remove(hls_player->client->main->lists, my_m3u8);
- break;
- }
-
- }
- }
-
- //hls_dump_m3u8 (hls_player->client->main);
- /* DUMP */
- hls_dump_playlist (hls_player);
- }
- else
- {
- g_print ("\n\n!!!!!!!!!!!!!!!! RELOADED but NO changes!!!!!!\n\n");
- }
-
- /* clean up */
- g_mapped_file_unref (file);
-
- return TRUE;
-
- debug_log (">>>\n");
-}
-
-
-gboolean hls_set_current_playlist (mm_player_hls_t *hls_player)
-{
- GList* copied = NULL;
- GList* tmp = NULL;
-
- debug_log ("<<<\n");
-
- if (hls_player->client->main->endlist)
- {
- debug_log ("main playlist has endlist. No need to set current playlist\n");
- return FALSE;
- }
-
- copied = g_list_copy (hls_player->client->main->lists);
- tmp = g_list_sort (copied, my_compare);
-
- /* Set initial bandwidth */
- if (tmp)
- {
- GstM3U8* data = (GstM3U8*)tmp->data;
-
- if (data)
- {
- debug_log ("Set Initial bandwidth\n");
- gst_m3u8_client_set_current (hls_player->client, data);
- debug_log ("Setting to initial BW = %d\n", data->bandwidth);
- tmp = g_list_next(tmp);
- }
- else
- {
- debug_error ("Initial media data is not valid!!!\n");
- g_list_free (copied);
- return FALSE;
- }
- }
- g_list_free (copied);
-
- debug_log (">>>\n");
-
- return TRUE;
-}
-
-gchar *hls_get_current_playlist (mm_player_hls_t *hls_player)
-{
- return hls_player->client->current->uri;
-}
-
-gboolean hls_has_variant_playlist (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- if ( gst_m3u8_client_has_variant_playlist (hls_player->client))
- {
- return TRUE;
- }
- else
- {
- debug_log ("playlist is simple playlist file....");
- return FALSE;
- }
-}
-
-gboolean hls_is_variant_playlist (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- if ( gst_m3u8_client_has_variant_playlist (hls_player->client) && (hls_player->client->current->files == NULL))
- {
- return TRUE;
- }
- else
- {
- debug_log ("playlist is simple playlist file....");
- return FALSE;
- }
-}
-
-gboolean
-hls_downloaded_variant_playlist (void *hls_handle, gchar *cur_mf_uri)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- if ( gst_m3u8_client_has_variant_playlist (hls_player->client))
- {
- if (!strcmp(hls_player->client->main->uri, cur_mf_uri))
- {
- debug_log ("downloaded variant master playlist...\n");
- return TRUE;
- }
- else
- {
- debug_log ("downloaded slave playlist file...\n");
- return FALSE;
- }
- }
- else
- {
- debug_log ("playlist is simple one...\n");
- return FALSE;
- }
-
-}
-
-gboolean hls_can_switch (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- return gst_m3u8_client_has_variant_playlist (hls_player->client);
-}
-
-
-gboolean hls_client_is_live (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- return gst_m3u8_client_is_live(hls_player->client);
-}
-
-gboolean hls_playlist_update_interval (void *hls_handle, GTimeVal *next_update)
-{
- gfloat update_factor;
- gint count;
- guint64 update = 0;
-
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- count = hls_player->client->update_failed_count;
- if (count < 3)
- update_factor = update_interval_factor[count];
- else
- update_factor = update_interval_factor[3];
-
- if (hls_player->client->current->targetduration == 0)
- {
- hls_player->client->current->targetduration = 10; //hack
- }
- g_time_val_add (next_update, hls_player->client->current->targetduration * update_factor * 1000000);
-
- update = (next_update->tv_sec * 1000000)+ next_update->tv_usec;
-
-
- return TRUE;
-}
-
-gboolean
-hls_determining_next_file_load (void *hls_handle, gboolean *is_ready)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- debug_log ("<<<\n");
-
- if (gst_m3u8_client_is_live(hls_player->client))
- {
- /* If next file is playable, then let it start */
- if (gst_m3u8_client_check_next_fragment (hls_player->client))
- {
- *is_ready = TRUE;
- }
- else
- {
- *is_ready = FALSE;
- debug_log ("Not ready to play next file!!!!! wait for reloading........\n");
- }
- }
- else
- {
- *is_ready = TRUE;
- debug_log ("No available media and ENDLIST exists, so Do nothing!!!! ");
- }
-
- debug_log (">>>\n");
- return FALSE;
-}
-
-
-
-static gboolean
-hls_switch_to_upperband (mm_player_hls_t * ahs_player, GList *next_bw_lists, guint download_rate)
-{
- GstM3U8 *next_client = NULL;
- GList *final_bw_lists = NULL;
-
- while (1)
- {
- next_client = (GstM3U8 *)next_bw_lists->data;
- if (download_rate > (next_client->bandwidth + (BITRATE_SWITCH_UPPER_THRESHOLD * next_client->bandwidth)))
- {
- final_bw_lists = next_bw_lists;
- next_bw_lists = g_list_next (next_bw_lists);
- if (NULL == next_bw_lists)
- {
- debug_log ("\n****** reached max BW possible.... *********\n");
- ahs_player->client->main->lists = final_bw_lists;
- gst_m3u8_client_set_current (ahs_player->client, final_bw_lists->data);
- debug_log("Client is MAX FAST, switching to bitrate %d\n", ahs_player->client->current->bandwidth);
- break;
- }
- }
- else
- {
- // TODO: Wrong condition.. need to check
- #if 0
- ahs_player->client->main->lists = final_bw_lists;
- gst_m3u8_client_set_current (ahs_player->client, final_bw_lists->data);
- #endif
- debug_log("Client is FAST, switching to bitrate %d\n", ahs_player->client->current->bandwidth);
- break;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-hls_switch_to_lowerband (mm_player_hls_t * player, guint download_rate)
-{
- GList *cur_bw_lists = player->client->main->lists;
- GList *prev_bw_lists = NULL;
- GList *present_bw_lists = player->client->main->lists;
- GstM3U8 *cur_client = (GstM3U8 *)cur_bw_lists->data;;
- GstM3U8 *present_client = NULL;
-
- while (1)
- {
- present_client = (GstM3U8 *)present_bw_lists->data;
-
- if (download_rate < (present_client->bandwidth + (BITRATE_SWITCH_LOWER_THRESHOLD * present_client->bandwidth)))
- {
- prev_bw_lists = present_bw_lists;
-
- if(NULL == present_bw_lists->prev)
- {
- if (cur_client->bandwidth == present_client->bandwidth)
- {
- debug_log ("\n\n\n We are at same lower BW\n\n\n");
- return TRUE;
- }
- debug_log ("\n****** reached min BW possible.... *********\n\n");
- player->client->main->lists = prev_bw_lists;
- gst_m3u8_client_set_current (player->client, prev_bw_lists->data);
- debug_log("Client is MAX SLOW, switching to bitrate %d\n", player->client->current->bandwidth);
- return TRUE;
- }
-
- present_bw_lists = g_list_previous (present_bw_lists);
-
- }
- else
- {
- player->client->main->lists = present_bw_lists;
- gst_m3u8_client_set_current (player->client, present_bw_lists->data);
- debug_log ("Client is SLOW, switching to bitrate %d\n", player->client->current->bandwidth);
- break;
- }
- }
-
- return TRUE;
-}
-
-gboolean hls_switch_playlist (void *hls_handle, guint download_rate, gboolean *need_bw_switch)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- GList *next_bw_lists = NULL;
- GstM3U8 *next_client = NULL;
- GList *present_bw_lists = NULL;
- GstM3U8 *present_client = NULL;
- GList *prev_bw_lists = NULL;
- GstM3U8 *prev_client = NULL;
-
- present_bw_lists = hls_player->client->main->lists;
- present_client = (GstM3U8 *)present_bw_lists->data;
- if (NULL == present_client)
- {
- g_print ("\n\n ERROR : Present client is NULL\n\n");
- return FALSE;
- }
-
- next_bw_lists = g_list_next (hls_player->client->main->lists);
- if (next_bw_lists)
- {
- next_client = (GstM3U8 *)next_bw_lists->data;
- }
-
- prev_bw_lists = g_list_previous (hls_player->client->main->lists);
- if (prev_bw_lists)
- {
- prev_client = (GstM3U8 *)prev_bw_lists->data;
- }
-
- if (next_bw_lists && (download_rate > (next_client->bandwidth + (BITRATE_SWITCH_UPPER_THRESHOLD * next_client->bandwidth))))
- {
- /* our download rate is 40% more than next bandwidth available */
- hls_switch_to_upperband (hls_player, next_bw_lists, download_rate);
- g_print (">>>>>>> Need to switch to UPPER BW [ %d ]\n", hls_player->client->current->bandwidth);
-
- *need_bw_switch = TRUE;
- }
- if (prev_bw_lists && (download_rate < (present_client->bandwidth + (BITRATE_SWITCH_LOWER_THRESHOLD * present_client->bandwidth))))
- {
- hls_switch_to_lowerband (hls_player, download_rate);
- g_print ("<<<<< Need to switch to LOWER BW [ %d ]\n", hls_player->client->current->bandwidth);
- *need_bw_switch = TRUE;
- }
-
- return TRUE;
-}
-
-gboolean hls_get_next_media_fragment (void *hls_handle, gchar **media_uri, gchar **key_uri, char **iv)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
- GstM3U8MediaFile *next_fragment_file = NULL;
- gboolean discontinuity = FALSE;
- char *tmp_iv = NULL;
-
- /* Get Next file to download */
- next_fragment_file = gst_m3u8_client_get_next_fragment (hls_player->client, &discontinuity);
- if (next_fragment_file)
- {
- hls_player->discontinuity = discontinuity;
- if (discontinuity)
- g_print ("\n\n\n!!!!!!!!! Discontinuity in fragments.....!!!!!!!!\n\n\n");
-
- debug_log ("media uri = %s and key_url = %s\n",next_fragment_file->uri, next_fragment_file->key_url);
- if (next_fragment_file->key_url)
- {
- tmp_iv = *iv;
- int i;
-
- for (i = 0; i< 16; i++)
- {
- debug_log ("%x", next_fragment_file->iv[i]);
- tmp_iv[i] = next_fragment_file->iv[i];
- }
- *iv = tmp_iv;
- *key_uri = g_strdup (next_fragment_file->key_url);
- }
- if (next_fragment_file->uri)
- {
- *media_uri = g_strdup (next_fragment_file->uri);
- }
- }
- else
- {
- debug_log ("\n\n ++++++++ No fragment remaining..... +++++++++\n\n");
- return TRUE;
- }
- return TRUE;
-}
-
-gboolean
-hls_is_buffer_discontinuous (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- return hls_player->discontinuity;
-}
-
-gboolean
-hls_clear_discontinuous (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- hls_player->discontinuity = 0;
-
- return TRUE;
-}
-
-gboolean
-hls_check_allow_cache (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- // TODO: doing intentioanlly for testing
- return FALSE;
-
- /* if allow_cache tag exists and if it is NO.. then dont cache media file. Otherwise, client can cache */
- if (gst_m3u8_client_allow_cache(hls_player->client) &&
- (!strncmp (gst_m3u8_client_allow_cache(hls_player->client), "NO", 2)))
- {
- debug_log ("\nClient SHOULD NOT cache media content...\n");
- return FALSE;
- }
- else
- {
- debug_log ("\nClient MAY cache media content...\n");
- return TRUE;
- }
-
-}
-
-gboolean
-hls_store_media_presentation (void *hls_handle, unsigned char *buffer, unsigned int buffer_len)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
- gint fd = -1;
- gint written = 0;
-
- if (NULL == hls_player->allow_cache_fd)
- {
- gchar *name = NULL;
-
- /* make copy of the template, we don't want to change this */
- name = g_strdup ("/tmp/XXXXXX");
-
- g_print ("\n========> Cached filename = %s\n", name);
-
- fd = g_mkstemp (name);
-
- g_free(name);
-
- if (fd == -1)
- {
- g_print ("\n\n\nFailed to create tmp file for writing...\n\n\n");
- return FALSE;
- }
-
- /* open the file for update/writing */
- hls_player->allow_cache_fd = fdopen (fd, "wb+");
- if (NULL == hls_player->allow_cache_fd)
- {
- g_print ("Failed to create allow cache file ptr\n\n\n");
- return FALSE;
- }
- }
-
-
- written = fwrite (buffer, 1, buffer_len, hls_player->allow_cache_fd);
- debug_log ("Cache file written %d bytes ....", written);
-
- return TRUE;
-
-}
-
-gboolean hls_decryption_initialize (void *hls_handle, gchar *key_data, unsigned char *iv)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- EVP_CIPHER_CTX_init(&(hls_player->decrypt));
- EVP_DecryptInit_ex(&(hls_player->decrypt), EVP_aes_128_cbc(), NULL, key_data, iv);
-
- return TRUE;
-}
-
-gboolean
-hls_decrypt_media_fragment (void *hls_handle,GstBuffer *InBuf, GstBuffer **OutBuf)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- unsigned int inbuf_size = 0;
- unsigned char *inbuf_data = NULL;
- int remain = 0;
- unsigned int out_len = 0;
- GstBuffer *buffer = NULL;
-
- if (hls_player->remained)
- {
- buffer = gst_buffer_merge (hls_player->remained, InBuf);
- if (NULL == buffer)
- {
- g_print ("ERROR: Failed to merge...\n");
- return FALSE;
- }
-
- gst_buffer_unref (hls_player->remained);
- hls_player->remained = NULL;
- }
- else
- {
- buffer = InBuf;
- }
-
- inbuf_size = GST_BUFFER_SIZE (buffer);
- inbuf_data = GST_BUFFER_DATA (buffer);
-
- remain = inbuf_size % AES_BLOCK_SIZE;
-
- if (remain)
- {
- hls_player->remained = gst_buffer_new_and_alloc (remain);
- if (NULL == hls_player->remained)
- {
- g_print ("Error: failed to allocate memory...\n");
- return FALSE;
- }
-
- /* copy remained portion to buffer */
- memcpy (GST_BUFFER_DATA(hls_player->remained), inbuf_data + inbuf_size- remain, remain);
- }
-
- out_len = inbuf_size - remain + AES_BLOCK_SIZE;
-
- *OutBuf = gst_buffer_new_and_alloc (out_len);
- if (NULL == *OutBuf)
- {
- g_print ("Failed to allocate memory for OutBuf...\n");
- return FALSE;
- }
-
- EVP_DecryptUpdate(&(hls_player->decrypt), GST_BUFFER_DATA(*OutBuf), &out_len, inbuf_data, inbuf_size - remain);
-
- GST_BUFFER_SIZE (*OutBuf) = out_len;
-
- return TRUE;
-
-}
-
-void * __mm_player_hls_create ()
-{
- mm_player_hls_t *hls_player = NULL;
-
- hls_player = (mm_player_hls_t *) malloc (sizeof (mm_player_hls_t));
- if (NULL == hls_player)
- {
- debug_error ("Failed to created ahs_player handle...\n");
- return NULL;
- }
-
- return (void *)hls_player;
-}
-
-gboolean __mm_player_hls_destroy (void *hls_handle)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- if (hls_player->uri)
- {
- g_free (hls_player->uri);
- hls_player->uri = NULL;
- }
-
- if (hls_player->client)
- {
- gst_m3u8_client_free (hls_player->client);
- hls_player->client = NULL;
- }
-
- free (hls_player);
-
- return TRUE;
-
-}
-
-gboolean __mm_player_hls_initialize (void *hls_handle, gchar *uri)
-{
- mm_player_hls_t *hls_player = (mm_player_hls_t *) hls_handle;
-
- hls_player->uri = g_strdup (uri);
-
- hls_player->client = gst_m3u8_client_new (hls_player->uri);
- if (NULL == hls_player->client)
- {
- debug_error ("Failed to create HLS client\n");
- return FALSE;
- }
-
- hls_player->remained = NULL;
- hls_player->allow_cache_fd = NULL;
-
- return TRUE;
-}
-
-
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com>
- *
- * m3u8.c:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* This source code is taken from m3u8.c, which is licensed by GNU Library General Public License.
- * AES-128 bit decryption features are changed from m3u8.c.
- * - gst_m3u8_update and gst_m3u8_media_file_new are modified.
- * - gst_m3u8_getIV_from_mediasequence is added.
- * For convenience,
- * - gst_m3u8_client_get_next_fragment is modified.
- * - gst_m3u8_client_check_next_fragment is added.
- * File name is changed to mm_player_m3u8.c
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <glib.h>
-
-#include "mm_player_m3u8.h"
-#include <mm_debug.h>
-#include <string.h>
-
-
-static GstM3U8 *gst_m3u8_new (void);
-static void gst_m3u8_free (GstM3U8 * m3u8);
-static gboolean gst_m3u8_update (GstM3U8 * m3u8, gchar * data,
- gboolean * updated);
-static GstM3U8MediaFile *gst_m3u8_media_file_new (gchar * uri, gchar * title, gint duration, gchar *key_url, gchar *IV, guint sequence);
-static void gst_m3u8_media_file_free (GstM3U8MediaFile * self);
-
-static GstM3U8 *
-gst_m3u8_new (void)
-{
- GstM3U8 *m3u8;
-
- m3u8 = g_new0 (GstM3U8, 1);
-
- return m3u8;
-}
-
-static void
-gst_m3u8_set_uri (GstM3U8 * self, gchar * uri)
-{
- g_return_if_fail (self != NULL);
-
- if (self->uri)
- g_free (self->uri);
- self->uri = uri;
-}
-
-static void
-gst_m3u8_free (GstM3U8 * self)
-{
- g_return_if_fail (self != NULL);
-
- g_free (self->uri);
- g_free (self->allowcache);
- g_free (self->codecs);
-
- g_list_foreach (self->files, (GFunc) gst_m3u8_media_file_free, NULL);
- g_list_free (self->files);
-
- g_free (self->last_data);
- g_list_foreach (self->lists, (GFunc) gst_m3u8_free, NULL);
- g_list_free (self->lists);
-
- g_free (self);
-}
-
-static GstM3U8MediaFile *
-gst_m3u8_media_file_new (gchar * uri, gchar * title, gint duration, gchar *key_url, gchar *IV, guint sequence)
-{
- GstM3U8MediaFile *file;
-
- file = g_new0 (GstM3U8MediaFile, 1);
- file->uri = uri;
- file->title = title;
- file->duration = duration;
- file->sequence = sequence;
- memset (file->key, 0x00, sizeof (file->key));
-
- //g_print (" uri = %s / ", uri);
-
- if (key_url != NULL)
- {
- file->key_url = g_strdup (key_url);
- }
- else
- file->key_url = NULL;
-
- if (IV != NULL)
- {
- memcpy (file->iv, IV, sizeof (file->iv));
- }
- return file;
-}
-
-static void
-gst_m3u8_media_file_free (GstM3U8MediaFile * self)
-{
- g_return_if_fail (self != NULL);
-
- if (self->key_url)
- g_free (self->key_url);
-
- g_free (self->title);
- g_free (self->uri);
- g_free (self);
-}
-
-static gchar *
-gst_m3u8_getIV_from_mediasequence (GstM3U8 *self)
-{
- gchar *IV = NULL;
- gint i = 0;
-
- IV = g_malloc0 (16);
- if (NULL == IV)
- {
- debug_warning ("Failed to allocate memory...");
- return NULL;
- }
-
- if (self->mediasequence > INT_MAX)
- {
- debug_warning ("media sequnece is greater than INT_MAX...yet to handle");
- }
-
- IV [15] = (gchar)(self->mediasequence);
- IV [14] = (gchar)(self->mediasequence >> 8);
- IV [13] = (gchar)(self->mediasequence >> 16);
- IV [12] = (gchar)(self->mediasequence >> 24);
-
- return IV;
-}
-
-static gboolean
-int_from_string (gchar * ptr, gchar ** endptr, gint * val, gint base)
-{
- gchar *end;
-
- g_return_val_if_fail (ptr != NULL, FALSE);
- g_return_val_if_fail (val != NULL, FALSE);
-
- errno = 0;
- *val = strtol (ptr, &end, base);
- if ((errno == ERANGE && (*val == LONG_MAX || *val == LONG_MIN))
- || (errno != 0 && *val == 0)) {
-// debug_warning (g_strerror (errno));
- return FALSE;
- }
-
- if (endptr)
- *endptr = end;
-
- return end != ptr;
-}
-
-static gboolean
-parse_attributes (gchar ** ptr, gchar ** a, gchar ** v)
-{
- gchar *end, *p;
-
- g_return_val_if_fail (ptr != NULL, FALSE);
- g_return_val_if_fail (*ptr != NULL, FALSE);
- g_return_val_if_fail (a != NULL, FALSE);
- g_return_val_if_fail (v != NULL, FALSE);
-
- /* [attribute=value,]* */
-
- *a = *ptr;
- end = p = g_utf8_strchr (*ptr, -1, ',');
- if (end) {
- do {
- end = g_utf8_next_char (end);
- } while (end && *end == ' ');
- *p = '\0';
- }
-
- *v = p = g_utf8_strchr (*ptr, -1, '=');
- if (*v) {
- *v = g_utf8_next_char (*v);
- *p = '\0';
- } else {
- debug_warning ("missing = after attribute\n");
- return FALSE;
- }
-
- *ptr = end;
- return TRUE;
-}
-
-static gint
-_m3u8_compare_uri (GstM3U8 * a, gchar * uri)
-{
- g_return_val_if_fail (a != NULL, 0);
- g_return_val_if_fail (uri != NULL, 0);
-
- return g_strcmp0 (a->uri, uri);
-}
-
-static gint
-gst_m3u8_compare_playlist_by_bitrate (gconstpointer a, gconstpointer b)
-{
- return ((GstM3U8 *) (a))->bandwidth - ((GstM3U8 *) (b))->bandwidth;
-}
-
-/*
- * @data: a m3u8 playlist text data, taking ownership
- */
-static gboolean
-gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated)
-{
- gint val, duration;
- gchar *title, *end;
- gboolean discontinuity;
- GstM3U8 *list;
- gchar *key_url = NULL;
- gchar *IV = NULL;
-
- g_return_val_if_fail (self != NULL, FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
- g_return_val_if_fail (updated != NULL, FALSE);
-
- *updated = TRUE;
-
- /* check if the data changed since last update */
- if (self->last_data && g_str_equal (self->last_data, data)) {
- g_print ("\n\n\n\t\t ############ Playlist is the same as previous one ############\n\n\n\n");
- *updated = FALSE;
- g_free (data);
- return TRUE;
- }
-
- if (!g_str_has_prefix (data, "#EXTM3U")) {
- debug_warning ("Data doesn't start with #EXTM3U\n");
- g_free (data);
- return FALSE;
- }
-
- /* playlist has changed from last time.. update last_data */
- g_free (self->last_data);
- self->last_data = data;
-
- if (self->files) {
- g_list_foreach (self->files, (GFunc) gst_m3u8_media_file_free, NULL);
- g_list_free (self->files);
- self->files = NULL;
- }
-
- list = NULL;
- duration = -1;
- title = NULL;
- key_url = NULL;
- data += 7;
- //data += 8;
- while (TRUE) {
- //g_print ("====================================\n");
- //g_print ("data = [%s]\n", data);
- end = g_utf8_strchr (data, -1, '\n'); /* FIXME: support \r\n */
- if (end)
- *end = '\0';
-
- //g_print ("end = [%s]\n", end);
-
-
- if (data[0] != '#') {
- if (duration < 0 && list == NULL) {
- debug_log ("%s: got line without EXTINF or EXTSTREAMINF, dropping\n", data);
- goto next_line;
- }
-
- if (!gst_uri_is_valid (data)) {
- gchar *slash;
- if (!self->uri) {
- debug_warning ("uri not set, can't build a valid uri\n");
- goto next_line;
- }
- slash = g_utf8_strrchr (self->uri, -1, '/');
- if (!slash) {
- debug_warning ("Can't build a valid uri\n");
- goto next_line;
- }
-
- *slash = '\0';
- data = g_strdup_printf ("%s/%s", self->uri, data);
- *slash = '/';
- } else
- data = g_strdup (data);
-
- if (list != NULL) {
- if (g_list_find_custom (self->lists, data,
- (GCompareFunc) _m3u8_compare_uri)) {
- debug_log ("Already have a list with this URI\n");
- gst_m3u8_free (list);
- g_free (data);
- } else {
- gst_m3u8_set_uri (list, data);
- self->lists = g_list_append (self->lists, list);
- }
- list = NULL;
- } else {
- GstM3U8MediaFile *file;
- gchar *send_IV = NULL;
-
- if (key_url)
- {
- debug_log ("AES-128 key url = %s", key_url);
- if (NULL == IV)
- {
- /* IV is not present in EXT-X-KEY tag. Prepare IV based on mediasequence */
- debug_log ("IV is not in EXT-X-KEY tag... generating from media_seq_num = %d", self->mediasequence);
- send_IV = gst_m3u8_getIV_from_mediasequence (self);
- }
- else
- {
- send_IV = g_strdup (IV);
- }
- }
-
- file =
- gst_m3u8_media_file_new (data, title, duration, key_url, send_IV, self->mediasequence++);
- duration = -1;
- title = NULL;
- g_free (send_IV);
- self->files = g_list_append (self->files, file);
- }
-
- } else if (g_str_has_prefix (data, "#EXT-X-ENDLIST")) {
- self->endlist = TRUE;
- } else if (g_str_has_prefix (data, "#EXT-X-VERSION:")) {
- if (int_from_string (data + 15, &data, &val, 10))
- self->version = val;
- } else if (g_str_has_prefix (data, "#EXT-X-STREAM-INF:")) {
- gchar *v, *a;
-
- if (list != NULL) {
- debug_warning ("Found a list without a uri..., dropping\n");
- gst_m3u8_free (list);
- }
-
- list = gst_m3u8_new ();
- data = data + 18;
- while (data && parse_attributes (&data, &a, &v)) {
- if (g_str_equal (a, "BANDWIDTH")) {
- if (!int_from_string (v, NULL, &list->bandwidth, 10))
- debug_warning ("Error while reading BANDWIDTH");
- } else if (g_str_equal (a, "PROGRAM-ID")) {
- if (!int_from_string (v, NULL, &list->program_id, 10))
- debug_warning ("Error while reading PROGRAM-ID");
- } else if (g_str_equal (a, "CODECS")) {
- g_free (list->codecs);
- list->codecs = g_strdup (v);
- } else if (g_str_equal (a, "RESOLUTION")) {
- if (!int_from_string (v, &v, &list->width, 10))
- debug_warning ("Error while reading RESOLUTION width");
- if (!v || *v != '=') {
- debug_warning ("Missing height\n");
- } else {
- v = g_utf8_next_char (v);
- if (!int_from_string (v, NULL, &list->height, 10))
- debug_warning ("Error while reading RESOLUTION height");
- }
- }
- }
- } else if (g_str_has_prefix (data, "#EXT-X-TARGETDURATION:")) {
- if (int_from_string (data + 22, &data, &val, 10))
- self->targetduration = val;
- // g_print ("\n\n\t\t#########################\n");
- //g_print ("\t\tTarget duration = %d\n", val);
- // g_print ("\n\n\t\t#########################\n");
-
- } else if (g_str_has_prefix (data, "#EXT-X-MEDIA-SEQUENCE:")) {
- if (int_from_string (data + 22, &data, &val, 10))
- self->mediasequence = val;
- } else if (g_str_has_prefix (data, "#EXT-X-DISCONTINUITY")) {
- discontinuity = TRUE;
- } else if (g_str_has_prefix (data, "#EXT-X-PROGRAM-DATE-TIME:")) {
- /* <YYYY-MM-DDThh:mm:ssZ> */
- debug_log ("FIXME parse date\n");
- } else if (g_str_has_prefix (data, "#EXT-X-ALLOW-CACHE:")) {
- g_free (self->allowcache);
- self->allowcache = g_strdup (data + 19);
- } else if (g_str_has_prefix (data, "#EXTINF:")) {
- if (!int_from_string (data + 8, &data, &val, 10)) {
- debug_warning ("Can't read EXTINF duration\n");
- goto next_line;
- }
- duration = val;
- if (duration > self->targetduration)
- debug_warning ("EXTINF duration > TARGETDURATION\n");
- if (!data || *data != ',')
- goto next_line;
- data = g_utf8_next_char (data);
- if (data != end) {
- g_free (title);
- title = g_strdup (data);
- }
- }else if (g_str_has_prefix (data, "#EXT-X-KEY:")){
- gchar *val, *attr;
-
-
- g_print ("\n\n Found EXT-X-KEY tag...\n\n");
- /* handling encrypted content */
-
- data = data + 11; /* skipping "#EXT-X-KEY:" tag */
-
- while (data && parse_attributes (&data, &attr, &val))
- {
- if (g_str_equal (attr, "METHOD"))
- {
- if (g_str_equal (val, "NONE"))
- {
- g_print ("Non encrypted file...and skipping current line and going to next line\n");
- goto next_line;
- }
- else if (g_str_equal (val, "AES-128"))
- {
- /* media files are encrypted */
- g_print ("media files are encrypted with AES-128");
- // TODO: indicate in flag whether encrypted files or not
- }
- }
- else if (g_str_equal (attr, "URI"))
- {
- gchar *end_dq = NULL;
-
- if (val == NULL)
- {
- debug_error ("val is NULL");
- break;
- }
-
- val = val + 1; /* eliminating first double quote in url */
- if (val == NULL)
- {
- debug_error ("val is NULL");
- break;
- }
-
- end_dq = g_utf8_strrchr (val, -1, '"');
- if (!end_dq)
- {
- debug_error ("end_dq is NULL");
- break;
- }
-
- *end_dq = '\0';
-
- g_print ("Key URI = %s\n", val);
-
- if (!gst_uri_is_valid (val))
- {
- gchar *slash;
- if (!self->uri)
- {
- debug_warning ("uri not set, can't build a valid uri");
- goto next_line;
- }
- slash = g_utf8_strrchr (self->uri, -1, '/');
- if (!slash)
- {
- debug_warning ("Can't build a valid uri");
- goto next_line;
- }
- *slash = '\0';
- key_url = g_strdup_printf ("%s/%s", self->uri, val);
- *slash = '/';
- }
- else
- {
- key_url= g_strdup (val);
- }
- }
- else if (g_str_equal (attr, "IV"))
- {
- gint iv_len = 0;
- gchar tmp_byte[3];
- gint tmp_val = 0;
- gint idx = 0;
-
- if (IV)
- {
- g_free (IV);
- IV = NULL;
- }
-
- IV = g_malloc0 (16);
- if (NULL == IV)
- {
- debug_error ("Failed to allocate memory...\n");
- return FALSE;
- }
-
- /* eliminating 0x/0X prefix */
- val = val + 2;
- iv_len = g_utf8_strlen(val, 0);
- if (iv_len != 16)
- {
- debug_warning ("Wrong IV...");
- return FALSE;
- }
-
- while (iv_len)
- {
- // TODO: val need to incremented I feel.. check again
- g_utf8_strncpy(tmp_byte, val, 2);
- tmp_byte[2] = '\0';
- tmp_val = 0;
- if (!int_from_string (tmp_byte, NULL, &tmp_val, 16))
- debug_warning ("Error while reading PROGRAM-ID");
- IV[idx] = tmp_val;
- idx++;
- iv_len = iv_len - 2;
- val = val + 2;
- }
- }
- }
-
-#if 0
- if (g_str_has_prefix (data, "METHOD="))
- {
- data = data + 7;
- if (g_str_has_prefix (data, "AES-128"))
- {
- g_print ("AES-128 encrypted media...\n\n");
- data = data + 8;
- if (g_str_has_prefix (data, "URI="))
- {
- gchar *dob_qu = NULL;
- gchar *tmp_key_url = NULL;
-
- data = data+5;
-
- dob_qu = g_utf8_strrchr (data, -1, '"');
- *dob_qu = '\0';
-
- tmp_key_url = g_strdup (data);
- *dob_qu = '"';
-
- g_print ("URI attribute = %s\n\n", tmp_key_url);
-
- if (!gst_uri_is_valid (tmp_key_url))
- {
- gchar *slash;
- if (!self->uri) {
- debug_warning ("uri not set, can't build a valid uri");
- goto next_line;
- }
- slash = g_utf8_strrchr (self->uri, -1, '/');
- if (!slash)
- {
- debug_warning ("Can't build a valid uri");
- goto next_line;
- }
-
- *slash = '\0';
- key_url = g_strdup_printf ("%s/%s", self->uri, tmp_key_url);
- *slash = '/';
- }
- else
- key_url = g_strdup (tmp_key_url);
-
- g_print ("\n\n======= Final key url = %s\n\n\n\n", key_url);
-
- data = dob_qu;
- data = data + 2;
-
- if ((g_str_has_prefix (data, "IV=0x")) && (g_str_has_prefix (data, "IV=0X")))
- {
- data = data + 5;
- g_print ("\n\nSize of IV = %d\n\n", sizeof (data));
- memcpy (IV, data, sizeof (IV));
- }
- else
- {
- g_print ("\n\n\n Need to generate IV from media sequence...\n\n");
- }
- }
- else
- {
- g_print ("No URI specified...\n\n");
- return FALSE;
- }
- }
- else if (g_str_has_prefix (data, "NONE"))
- {
- g_print ("\n\nNot encrypted.....\n\n\n");
- }
- else
- {
- g_print ("\n\nUnknown EXT-X-KEY METHOD attri = %s\n\n", data);
- return FALSE;
- }
- }
-
- else
- {
- g_print ("\n\nEXT-X-KEY without METHOD attribute...\n\n");
- return FALSE;
- }
-#endif
- }
- else {
- debug_warning ("Ignored line: %s", data);
- }
-
- next_line:
- if (!end)
- break;
- data = g_utf8_next_char (end); /* skip \n */
- }
-
- /* redorder playlists by bitrate */
- if (self->lists)
- self->lists =
- g_list_sort (self->lists,
- (GCompareFunc) gst_m3u8_compare_playlist_by_bitrate);
-
- return TRUE;
-}
-
-GstM3U8Client *
-gst_m3u8_client_new (const gchar * uri)
-{
- GstM3U8Client *client;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- client = g_new0 (GstM3U8Client, 1);
- client->main = gst_m3u8_new ();
- client->current = NULL;
- client->sequence = -1;
- client->update_failed_count = 0;
- gst_m3u8_set_uri (client->main, g_strdup (uri));
-
- return client;
-}
-
-void
-gst_m3u8_client_free (GstM3U8Client * self)
-{
- g_return_if_fail (self != NULL);
-
- gst_m3u8_free (self->main);
- g_free (self);
-}
-
-void
-gst_m3u8_client_set_current (GstM3U8Client * self, GstM3U8 * m3u8)
-{
- g_return_if_fail (self != NULL);
-
- if (m3u8 != self->current) {
- self->current = m3u8;
- self->update_failed_count = 0;
- }
-}
-
-gboolean
-gst_m3u8_client_update (GstM3U8Client * self, gchar * data)
-{
- GstM3U8 *m3u8;
- gboolean updated = FALSE;
-
- g_return_val_if_fail (self != NULL, FALSE);
-
- m3u8 = self->current ? self->current : self->main;
-
- // g_print ("\n\n");
-
- if (!gst_m3u8_update (m3u8, data, &updated))
- return FALSE;
-
- // g_print ("\n\n");
-
- if (!updated) {
- self->update_failed_count++;
- return FALSE;
- }
-
- /* select the first playlist, for now */
- if (!self->current) {
- if (self->main->lists) {
- self->current = g_list_first (self->main->lists)->data;
- } else {
- self->current = self->main;
- }
- }
-
- if (m3u8->files && self->sequence == -1) {
- self->sequence =
- GST_M3U8_MEDIA_FILE (g_list_first (m3u8->files)->data)->sequence;
- debug_log ("Setting first sequence at %d", self->sequence);
- }
-
- return TRUE;
-}
-
-static gboolean
-_find_next (GstM3U8MediaFile * file, GstM3U8Client * client)
-{
- debug_log ("Found fragment %d\n", file->sequence);
- if (file->sequence >= client->sequence)
- return FALSE;
- return TRUE;
-}
-
-const GstM3U8MediaFile *
-gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
- gboolean * discontinuity)
-{
- GList *l;
- GstM3U8MediaFile *file;
-
- g_return_val_if_fail (client != NULL, NULL);
- g_return_val_if_fail (client->current != NULL, NULL);
- g_return_val_if_fail (discontinuity != NULL, NULL);
-
- debug_log ("Looking for fragment %d\n", client->sequence);
- l = g_list_find_custom (client->current->files, client,
- (GCompareFunc) _find_next);
- if (l == NULL)
- return NULL;
-
- file = GST_M3U8_MEDIA_FILE (l->data);
-
- *discontinuity = client->sequence != file->sequence;
- client->sequence = file->sequence + 1;
-
- return file;
-}
-
-
-const gboolean
-gst_m3u8_client_check_next_fragment (GstM3U8Client * client)
-{
- gint left_duration = 0;
-
- g_return_val_if_fail (client != NULL, FALSE);
- g_return_val_if_fail (client->current != NULL, FALSE);
-
- GList* cur = g_list_last (client->current->files);
- while (cur && GST_M3U8_MEDIA_FILE(cur->data)->sequence >= client->sequence)
- {
- left_duration += GST_M3U8_MEDIA_FILE(cur->data)->duration;
- cur = g_list_previous (cur);
- }
-
- debug_log ("left duration = [%d], target duration[%d] * 3 = [%d]\n",
- left_duration, client->current->targetduration, client->current->targetduration*3);
-
- return (left_duration > client->current->targetduration*3)? TRUE : FALSE;
-
-}