From e5cff5a3ef373a5090f45cd1dfb0b85d9c851d5d Mon Sep 17 00:00:00 2001
From: FuJuntang <strongtiger_001@163.com>
Date: 星期三, 06 七月 2022 10:04:09 +0800
Subject: [PATCH] Add video recorder and playback support.

---
 service/ptz/ptz.c              |  164 ++---
 service/capabilities/capa.c    |   43 +
 test/av_test/av_test.c         |   66 ++
 service/av_demux/video_conv.sh |   58 ++
 service/ptz/ptz.h              |   24 
 Makefile                       |   11 
 test/probe_test/Makefile       |    5 
 service/av_demux/av_demux.h    |  100 +++
 comm/proto_comm.c              |  146 +++-
 service/av_demux/av_demux.c    |  810 +++++++++++++++++++++++++++++++
 test/ptz_test/ptz_test.c       |    2 
 comm/proto_dbg.h               |    3 
 test/av_test/Makefile          |   52 ++
 test/Makefile.inc              |    5 
 comm/proto_comm.h              |   46 +
 test/ptz_test/Makefile         |    5 
 16 files changed, 1,373 insertions(+), 167 deletions(-)

diff --git a/Makefile b/Makefile
index 593f2b1..a9a81be 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,8 @@
 RM           := rm
 
 CFLAGS += -c -Wall -DWITH_DOM -DWITH_NONAMESPACES -DWITH_OPENSSL
+CFLAGS += -DPROTOBUF_USS_DLLS
+CFLAGS += -fPIC -Wunused-function
 
 SOURCES_CORE += \
            core/soapC.c                          \
@@ -25,7 +27,8 @@
           service/probe/probe.c                 \
           service/deviceinfo/dev_info.c         \
           service/capabilities/capa.c           \
-          service/ptz/ptz.c                     
+          service/ptz/ptz.c                     \
+          service/av_demux/av_demux.c                    
 
 SOURCES_COMM += \
            comm/proto_dbg.c                      \
@@ -35,6 +38,7 @@
 OBJECTS_ONVIF_SRVS := $(patsubst %.c,$(TEMPDIR)%.o,$(filter %.c, $(SOURCES_SRVS)))
 OBJECTS_ONVIF_COMM  := $(patsubst %.c,$(TEMPDIR)%.o,$(filter %.c, $(SOURCES_COMM)))
 
+FFMPEG_DIR = thirdparty/ffmpeg
 OPENSSL_DIR = thirdparty/openssl
 
 TARGET_LIB = libonvif_std.so
@@ -42,18 +46,21 @@
 INCLUDE += -Icore/                               \
            -Icomm/         \
            -Iservice      \
+           -I$(FFMPEG_DIR)/include          \
            -I$(OPENSSL_DIR)/include
 CFLAGS += $(INCLUDE)
 
 CFLAGS += -Wno-unused
+LDFLAGS += -L$(FFMPEG_DIR)/lib
 LDFLAGS += -L$(OPENSSL_DIR)/lib
+LDFLAGS += -Lthirdparty
 LDLIBS += -lavcodec -lavdevice -lavfilter -lavformat \
            -lavutil -lswresample -lswscale
 LDLIBS += -lcrypto -lssl -lpthread -ldl -lrt -lm
 
 CFLAGS += -fPIC
 
-DIRS_TEST = test/probe_test test/ptz_test 
+DIRS_TEST = test/probe_test test/ptz_test test/av_test
 
 %.o: $(SOURCES_CORE)/%.cpp $(SOURCES_SRVS)/%.cpp $(SOURCES_COMM)/%.cpp
 	@echo "  CPP     " $@; 
diff --git a/comm/proto_comm.c b/comm/proto_comm.c
index df226ca..21c3c26 100644
--- a/comm/proto_comm.c
+++ b/comm/proto_comm.c
@@ -1,73 +1,131 @@
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <time.h>
+#include <signal.h>
+
 #include "proto_comm.h"
 #include "proto_dbg.h"
 
+int timer_init(timer_t *timer_index, void (*timer_handler)(union sigval para)) {
+  struct sigevent event;
+  timer_t timer;
+  int ret; 
+
+  memset(&event, 0x00, sizeof(event));
+  event.sigev_value.sival_int = ENABLE;
+  event.sigev_value.sival_ptr = NULL;
+  event.sigev_notify = SIGEV_THREAD;
+  event.sigev_notify_function = timer_handler;
+  
+  ret = timer_create(CLOCK_REALTIME, &event, &timer);
+  if (ret) {
+    return -1;
+  }
+
+  if (timer_index != NULL) {
+    *timer_index = timer;
+  }
+
+  return 0;
+}
+
+int timer_start(timer_t timer_index, int sec) {
+  int ret; 
+  struct itimerspec ts;
+
+  ts.it_interval.tv_sec = 0; 
+  ts.it_interval.tv_nsec = 0; 
+  ts.it_value.tv_sec = sec; 
+  ts.it_value.tv_nsec = 0; 
+  ret = timer_settime(timer_index, 0, &ts, NULL);
+  if (ret) {
+    return -1;
+  }
+
+  return ret; 
+}
+
+int timer_stop(timer_t timer_index) {
+
+  int ret = timer_start(timer_index, 0);
+
+  return ret;
+}
+
+int timer_destroy(timer_t timer_index) {
+  int ret;
+
+  ret = timer_delete(timer_index);
+
+  return ret;
+}
+
 void soap_perror(struct soap *soap, const char *str)
 {
-    if (NULL == str) {
-        SOAP_DBGERR("[soap] error: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
-    } else {
-        SOAP_DBGERR("[soap] %s error: %d, %s, %s\n", str, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
-    }
-    return;
+  if (NULL == str) {
+    SOAP_DBGERR("[soap] error: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
+  } else {
+    SOAP_DBGERR("[soap] %s error: %d, %s, %s\n", str, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
+  }
+    
+  return;
 }
 
 void* proto_soap_malloc(struct soap *soap, unsigned int n)
 {
-    void *p = NULL;
+  void *p = NULL;
 
-    if (n > 0) {
-        p = soap_malloc(soap, n);
-        SOAP_ASSERT(NULL != p);
-        memset(p, 0x00 ,n);
-    }
-    return p;
+  if (n > 0) {
+    p = soap_malloc(soap, n);
+    SOAP_ASSERT(NULL != p);
+    memset(p, 0x00 ,n);
+  }
+    
+  return p;
 }
 
 struct soap *proto_soap_new(int timeout)
 {
-    struct soap *soap = NULL;                                                   // soap环境变量
+  struct soap *soap = NULL;
 
-    SOAP_ASSERT(NULL != (soap = soap_new()));
+  SOAP_ASSERT(NULL != (soap = soap_new()));
 
-    soap_set_namespaces(soap, namespaces);                                      // 设置soap的namespaces
-    soap->recv_timeout    = timeout;                                            
-    soap->send_timeout    = timeout;
-    soap->connect_timeout = timeout;
+  soap_set_namespaces(soap, namespaces);
+  soap->recv_timeout    = timeout;                                            
+  soap->send_timeout    = timeout;
+  soap->connect_timeout = timeout;
 
 #if defined(__linux__) || defined(__linux)                                     
-    soap->socket_flags = MSG_NOSIGNAL;                                          
+  soap->socket_flags = MSG_NOSIGNAL;                                          
 #endif
 
-    soap_set_mode(soap, SOAP_C_UTFSTRING);                                    
+  soap_set_mode(soap, SOAP_C_UTFSTRING);                                    
 
-    return soap;
+  return soap;
 }
 
 void proto_soap_delete(struct soap *soap)
 {
-    soap_destroy(soap);                                                         // remove deserialized class instances (C++ only)
-    soap_end(soap);                                                             // Clean up deserialized data (except class instances) and temporary data
-    soap_done(soap);                                                            // Reset, close communications, and remove callbacks
-    soap_free(soap);                                                            // Reset and deallocate the context created with soap_new or soap_copy
+  soap_destroy(soap);                                                         // remove deserialized class instances (C++ only)
+  soap_end(soap);                                                             // Clean up deserialized data (except class instances) and temporary data
+  soap_done(soap);                                                            // Reset, close communications, and remove callbacks
+  soap_free(soap);                                                            // Reset and deallocate the context created with soap_new or soap_copy
 }
 
 int proto_SetAuthInfo(struct soap *soap, const char *username, const char *password)
 {
-    int result = 0;
+  int result = 0;
 
-    SOAP_ASSERT(NULL != username);
-    SOAP_ASSERT(NULL != password);
+  SOAP_ASSERT(NULL != username);
+  SOAP_ASSERT(NULL != password);
 
-    result = soap_wsse_add_UsernameTokenDigest(soap, NULL, username, password);
-    SOAP_CHECK_ERROR(result, soap, "add_UsernameTokenDigest");
+  result = soap_wsse_add_UsernameTokenDigest(soap, NULL, username, password);
+  SOAP_CHECK_ERROR(result, soap, "add_UsernameTokenDigest");
 
 EXIT:
 
-    return result;
+  return result;
 }
 
 float para_check(float data)
@@ -85,11 +143,6 @@
   return ret;
 }
 
-/************************************************************************
-  *初始化soap描述消息头
-
-  *在本函数内部通过proto_soap_malloc分配的内存,将在proto_soap_delete中被释放
-************************************************************************/
 void proto_init_header(struct soap *soap)
 {
     struct SOAP_ENV__Header *header = NULL;
@@ -109,27 +162,22 @@
     return;
 }
 
-/************************************************************************
-  *初始化探测设备的范围和类型
-
-  *在本函数内部通过proto_soap_malloc分配的内存,将在proto_soap_delete中被释放
-************************************************************************/
 void proto_init_ProbeType(struct soap *soap, struct wsdd__ProbeType *probe)
 {
-    struct wsdd__ScopesType *scope = NULL;                                      // 用于描述查找哪类的Web服务
+    struct wsdd__ScopesType *scope = NULL;
 
     SOAP_ASSERT(NULL != soap);
     SOAP_ASSERT(NULL != probe);
 
     scope = (struct wsdd__ScopesType *)proto_soap_malloc(soap, sizeof(struct wsdd__ScopesType));
-    soap_default_wsdd__ScopesType(soap, scope);                                 // 设置寻找设备的范围
+    soap_default_wsdd__ScopesType(soap, scope);
     scope->__item = (char*)proto_soap_malloc(soap, strlen(SOAP_ITEM) + 1);
     strcpy(scope->__item, SOAP_ITEM);
 
     memset(probe, 0x00, sizeof(struct wsdd__ProbeType));
     soap_default_wsdd__ProbeType(soap, probe);
     probe->Scopes = scope;
-    probe->Types  = (char*)proto_soap_malloc(soap, strlen(SOAP_TYPES) + 1);     // 设置寻找设备的类型
+    probe->Types  = (char*)proto_soap_malloc(soap, strlen(SOAP_TYPES) + 1);
     strcpy(probe->Types, SOAP_TYPES);
 
     return;
@@ -139,7 +187,7 @@
   *rtsp://100.100.100.140:554/av0_0
   *rtsp://username:password@100.100.100.140:554/av0_0
 ************************************************************************/
-int make_uri_withauth(char *src_uri, char *username, char *password, char *dest_uri, unsigned int size_dest_uri)
+int bridge_uri(char *src_uri, const char *username, const char *password, char *dest_uri, unsigned int size_dest_uri)
 {
     int result = 0;
     unsigned int needBufSize = 0;
@@ -150,14 +198,14 @@
     SOAP_ASSERT(NULL != dest_uri);
     memset(dest_uri, 0x00, size_dest_uri);
 
-    needBufSize = strlen(src_uri) + strlen(username) + strlen(password) + 3;    // 检查缓存是否足够,包括‘:’和‘@’和字符串结束符
+    needBufSize = strlen(src_uri) + strlen(username) + strlen(password) + 3;    //check buf size with character ‘:’ and ‘@'
     if (size_dest_uri < needBufSize) {
         SOAP_DBGERR("dest uri buf size is not enough.\n");
         result = -1;
         goto EXIT;
     }
 
-    if (0 == strlen(username) && 0 == strlen(password)) {                       // 生成新的uri地址
+    if (0 == strlen(username) && 0 == strlen(password)) {
         strcpy(dest_uri, src_uri);
     } else {
         char *p = strstr(src_uri, "//");
diff --git a/comm/proto_comm.h b/comm/proto_comm.h
index 9ca7239..97f3a0b 100644
--- a/comm/proto_comm.h
+++ b/comm/proto_comm.h
@@ -8,6 +8,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <time.h>
+#include <signal.h>
+
 #include "soapH.h"
 #include "soapStub.h"
 #include "wsaapi.h"
@@ -24,6 +27,10 @@
 #define min(a,b)    (((a) < (b)) ? (a) : (b))
 #endif
 
+#define WT_TIME         5
+#define STOP_WT_TIME    3
+#define WT_MAX_TIME     (60 * 20)
+
 #define SOAP_ASSERT     assert
 #define SOAP_DBGERR     printf
 
@@ -33,27 +40,46 @@
 #define SOAP_DBGLOG
 #endif 
 
+#define USERNAME        "On_admin"                                                
+#define PASSWORD        "a12345678"
+
 #define SOAP_TO         "urn:schemas-xmlsoap-org:ws:2005:04:discovery"
 #define SOAP_ACTION     "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"
 
 #define SOAP_MCAST_ADDR "soap.udp://239.255.255.250:3702"                      
 
-#define SOAP_ITEM       ""                                                      // 寻找的设备范围
-#define SOAP_TYPES      "dn:NetworkVideoTransmitter"                            // 寻找的设备类型
+#define SOAP_ITEM       ""
+#define SOAP_TYPES      "dn:NetworkVideoTransmitter"                            //device type
+
+#define ADDR_PREFIX     "http://"
+#define ADDR_LAST       "/"
+
+#define NAME_BRIDGE     "_"
+#define NAME_DOT        "."
+#define NAME_MID        "-"
 
 #define SOAP_SOCK_TIMEOUT    (10)                                               //sec
+
+#define TRUE                  1
+#define FALSE                 0
+
+#define ENABLE          0
+#define DISABLE         1
 
 #define PARA_MIN              (-1)
 #define PARA_MAX              (1)
 
-#define PROTO_ADDRESS_SIZE   (128)                                              // URI地址长度
-#define PROTO_TOKEN_SIZE     (65)                                               // token长度
+#define PROTO_ADDRESS_SIZE   (128)
+#define PROTO_TOKEN_SIZE     (65)                                               //token size
+#define PTOTO_ADDRESS_ADD    (65)
 
-/* 视频编码器配置信息 */
+#define MAX_BUF_SIZE    600
+
+/*video encoder configurations */
 struct tagVideoEncoderConfiguration
 {
-  char token[PROTO_TOKEN_SIZE];                                               // 唯一标识该视频编码器的令牌字符串
-  int Width;                                                                  // 分辨率
+  char token[PROTO_TOKEN_SIZE];                                               //video token
+  int Width;                                                                  //resolution
   int Height;
 };
 
@@ -78,6 +104,10 @@
         } \
     } while (0)
 
+int timer_init(timer_t *timer_index, void (*timer_handler)(union sigval para));
+int timer_start(timer_t timer_index, int sec);
+int timer_stop(timer_t timer_index);
+int timer_destroy(timer_t timer_index);
 
 void            soap_perror(struct soap *soap, const char *str);
 void *          proto_soap_malloc(struct soap *soap, unsigned int n);
@@ -89,7 +119,7 @@
 void            proto_init_ProbeType(struct soap *soap, struct wsdd__ProbeType *probe);
 float           para_check(float data);
 
-int             make_uri_withauth(char *src_uri, char *username, char *password, char *dest_uri, unsigned int size_dest_uri);
+int             bridge_uri(char *src_uri, const char *username, const char *password, char *dest_uri, unsigned int size_dest_uri);
 int             soap_wsse_add_UsernameTokenDigest(struct soap *soap, const char *id, const char *username, const char *password);
 
 int proto_GetDeviceInformation(const char *DeviceXAddr, const char *username, const char *passwd);
diff --git a/comm/proto_dbg.h b/comm/proto_dbg.h
index 5858a5f..f001b86 100644
--- a/comm/proto_dbg.h
+++ b/comm/proto_dbg.h
@@ -22,7 +22,6 @@
 };
 
 #ifdef PROTO_DEBUG
-
 void dump__wsdd__ProbeMatches(struct __wsdd__ProbeMatches *rep);
 void dump__GetPresetsResponse(struct _tptz__GetPresetsResponse *rep);
 void dump_tds__GetCapabilitiesResponse(struct _tds__GetCapabilitiesResponse *rep);
@@ -44,7 +43,6 @@
 void dump_trt__GetVideoEncoderConfigurationOptionsResponse(struct _trt__GetVideoEncoderConfigurationOptionsResponse *rep);
 void log_level_val(unsigned int level, const char *prestr, enum LOG_TYPE type, const void *val);
 #else
-
 #define dump__wsdd__ProbeMatches
 #define dump_tds__GetCapabilitiesResponse
 #define dump_tds__GetDeviceInformationResponse
@@ -63,6 +61,7 @@
 #define dump_trt__GetVideoEncoderConfigurationsResponse
 #define dump_trt__GetCompatibleVideoEncoderConfigurationsResponse
 #define dump_trt__GetVideoEncoderConfigurationOptionsResponse
+#define log_level_val
 
 #endif
 
diff --git a/service/av_demux/av_demux.c b/service/av_demux/av_demux.c
new file mode 100644
index 0000000..99dbf2c
--- /dev/null
+++ b/service/av_demux/av_demux.c
@@ -0,0 +1,810 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <sys/vfs.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "libavcodec/avcodec.h"
+#include "libavdevice/avdevice.h"
+#include "libavformat/avformat.h"
+#include "libavfilter/avfilter.h"
+#include "libavutil/avutil.h"
+#include "libswscale/swscale.h"
+#include "libavutil/pixdesc.h"
+
+#include "probe/probe.h"
+#include "av_demux/av_demux.h"
+#include "proto_comm.h"
+#include "proto_dbg.h"
+
+static AVDevs *gAVDevs = NULL;
+
+static int data_cmp(char *s1, char *s2, char *dlim);
+
+/*signal process interrupt handler*/
+static void handler(int sig) 
+{
+  sync();
+}
+
+void av_timer_handler(union sigval para) 
+{
+  gAVDevs->slice_stat = FALSE; 
+}
+
+/*parse the location to get the right direction*/
+static int get_dir_with_key(char *dir_path, char *name, char *key, char *buf, int length) {
+  DIR *pDir;
+  char *ptr;
+  char temp = 0;
+  char found = FALSE;
+  struct dirent * entry;
+  char parse_buf[MAX_BUF_SIZE] = { 0x00 };
+
+  pDir = opendir(dir_path);
+  if (  
+    pDir == NULL) {
+    SOAP_DBGERR("the path(%s) can not be opened!\n", dir_path);
+
+    return -1; 
+  }
+
+  while((entry = readdir(pDir)) != NULL) {   
+
+    if (entry->d_type & DT_DIR) {
+
+      if ((strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0)) { 
+
+        ptr = strstr(entry->d_name, NAME_BRIDGE);
+    
+        if ((ptr != NULL) && (strcmp(ptr + 1, name) == 0)) {
+    
+          if (data_cmp(entry->d_name, key, NAME_MID) <= 0) {
+    
+            found = TRUE;
+            if (temp == 0) {
+              memcpy(parse_buf, entry->d_name, sizeof(parse_buf));
+
+              temp = 1;
+
+            } else {
+    
+              if (data_cmp(parse_buf, entry->d_name, NAME_MID) < 0) {
+                memset(parse_buf, 0x00, sizeof(parse_buf));
+                memcpy(parse_buf, entry->d_name, sizeof(parse_buf));
+              }
+            }
+          }
+        }
+      }   
+    }
+  }
+
+  closedir(pDir);
+
+  if (found == TRUE) {
+    memcpy(buf, dir_path, length - 1);
+    memcpy(buf + strlen(buf), "/", length - strlen(buf) - 1);
+    memcpy(buf + strlen(buf), parse_buf, length - strlen(buf) - 1);
+  } else {
+    buf[0] = 0;
+  }
+
+  return found;
+}
+
+int playback_get_key(playback_key set, char *buf, int length) {
+  int ret;
+  char parse_buf[MAX_BUF_SIZE] = { 0x00 };
+  char buf_temp[MAX_BUF_SIZE] = { 0x00 };
+
+  if ((set.name == NULL) || (set.date == NULL) || (set.time == NULL)) {
+    SOAP_DBGERR("invalid playbeck key set parameters!\n");
+
+    return 0;
+  }
+
+  ret = get_dir_with_key(VIDEO_PUT_DIR, set.name, set.date, parse_buf, sizeof(parse_buf));
+  if (ret > 0) {
+    ret = get_file_with_key(parse_buf, set.time, buf_temp, sizeof(buf_temp), 0);
+    if (ret > 0) {
+      memcpy(buf, buf_temp, length);
+    }
+  }
+
+  return ret;
+}
+
+static int get_dir_oldest(char *dir_path, char *buf, int length) {
+  DIR *pDir;
+  char temp = 0;
+  int found = FALSE;
+  struct dirent * entry;
+  char parse_buf[MAX_BUF_SIZE] = { 0x00 };
+
+  pDir = opendir(dir_path);
+  if (   
+    pDir == NULL) {
+    SOAP_DBGERR("the path(%s) can not be opened!\n", dir_path);
+
+    return -1; 
+  }
+
+  while((entry = readdir(pDir)) != NULL) {   
+
+    if (entry->d_type & DT_DIR) {
+
+      if ((strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0)) { 
+
+        found = TRUE;
+        if (temp == 0) {
+          memcpy(parse_buf, entry->d_name, sizeof(parse_buf));
+
+          temp = 1;
+
+        } else {
+
+          if (data_cmp(parse_buf, entry->d_name, NAME_MID) > 0) {
+            memset(parse_buf, 0x00, sizeof(parse_buf));
+            memcpy(parse_buf, entry->d_name, sizeof(parse_buf));
+          }
+        }
+      }
+    }
+  }
+
+  closedir(pDir);
+
+  if (found == TRUE) {
+    memcpy(buf, dir_path, length);
+    memcpy(buf + strlen(buf), "/", length - strlen(buf) - 1);
+    memcpy(buf + strlen(buf), parse_buf, length - strlen(buf) - 1);
+
+    return 0;
+  }
+
+  buf[0] = 0x00;
+
+  return -1;
+}
+
+/*parse the location to get the right file.
+* flag - include the key itself or not
+*/
+static int get_file_with_key(char *dir_path, char *key, char *buf, int length, int flag) {
+  DIR *pDir;
+  char temp = 0;
+  char found = FALSE;
+  char found_flag = FALSE;
+  struct dirent * entry;
+  char parse_buf[MAX_BUF_SIZE] = { 0x00 };
+
+  pDir = opendir(dir_path);
+  if (pDir == NULL) {
+    SOAP_DBGERR("the path(%s) can not be opened!\n", dir_path);
+
+    return -1;
+  }
+
+  while((entry = readdir(pDir)) != NULL) {
+
+    if (entry->d_type & DT_REG) {
+
+      if ((key != NULL) && (data_cmp(key, entry->d_name, NAME_MID) >= 0)) {
+
+        if ((flag == 1) && (data_cmp(key, entry->d_name, NAME_MID) > 0)) {
+          found = TRUE;
+        } else if (flag == 0) {
+          found = TRUE;
+        }
+      } else if (key == NULL) {
+        found = TRUE;
+      }
+
+      if (found == TRUE) {
+
+        found_flag = TRUE;
+
+        if (temp == 0) {
+          memcpy(parse_buf, entry->d_name, sizeof(parse_buf));
+
+          temp = 1;
+
+        } else {
+
+          if (data_cmp(parse_buf, entry->d_name, NAME_MID) < 0) {
+            memset(parse_buf, 0x00, sizeof(parse_buf));
+            memcpy(parse_buf, entry->d_name, sizeof(parse_buf));
+          }
+        }
+
+        found = FALSE;
+      }
+    }
+  }
+
+  closedir(pDir);
+
+  if (found_flag == TRUE) {
+    memcpy(buf, dir_path, length - 1);
+    memcpy(buf + strlen(buf), "/", length - strlen(buf) - 1);
+    memcpy(buf + strlen(buf), parse_buf, length - strlen(buf) - 1);
+  } else {
+    buf[0] = 0;
+  }
+
+  return found_flag;
+}
+
+/*compare the string between s1 and s2*/
+static int data_cmp(char *s1, char *s2, char *dlim)
+{
+  int data1;
+  int data2;
+  char *ptr1;
+  char *ptr2;
+
+  data1 = atoi(s1);
+  data2 = atoi(s2);
+  if (data1 > data2)
+    return 1;
+
+  if (data1 < data2)
+    return -1;
+
+  ptr1 = strstr(s1, dlim);
+  ptr2 = strstr(s2, dlim);
+  data1 = atoi(ptr1 + 1);
+  data2 = atoi(ptr2 + 1);
+  if (data1 > data2)
+    return 1;
+
+  if (data1 < data2)
+    return -1;
+
+  ptr1 = strstr(ptr1 + 1, dlim);
+  ptr2 = strstr(ptr2 + 1, dlim);
+  data1 = atoi(ptr1 + 1);
+  data2 = atoi(ptr2 + 1);
+  if (data1 > data2)
+    return 1;
+
+  if (data1 < data2)
+    return -1;
+
+  return 0;
+}
+
+/*av stream capture task*/
+static void *task_av_capture(void *arg) 
+{
+  struct timespec time_exp;
+
+  time_exp.tv_sec =  WT_TIME;
+  time_exp.tv_nsec = 0; 
+  //int data = *(int *)arg;
+  
+  pthread_detach(pthread_self());
+
+  while(1) {
+    sem_timedwait(&(gAVDevs->sem_cap), &time_exp);
+
+    while(gAVDevs->run_stat == TRUE) {
+
+      av_start_cap(gAVDevs);
+      
+      gAVDevs->slice_stat = TRUE;
+      
+    }
+
+    if (gAVDevs->dev_stat == DISABLE) {
+     
+      gAVDevs->proc_stat = DISABLE;
+    
+    }
+  }
+
+  return 0;
+}
+
+/*monitor the disk usage*/
+static void *task_disk_mon(void *arg)
+{
+  int ret;
+  uint64_t blocksize;
+  uint64_t totalsize;
+  uint64_t availableDisk;
+  struct statfs diskInfo; 
+  char buf[MAX_BUF_SIZE] = { 0x00 };
+  char buf_cmd[MAX_BUF_SIZE] = { 0x00 };
+
+  pthread_detach(pthread_self());
+
+  while(1) {
+    statfs(VIDEO_PUT_DIR, &diskInfo);
+
+    blocksize = diskInfo.f_bsize;
+    totalsize = blocksize * diskInfo.f_blocks;
+    availableDisk = diskInfo.f_bavail * blocksize;
+
+    while ((availableDisk * 1.0 / totalsize) < DISK_FREE_THRES) {
+      ret = get_dir_oldest(VIDEO_PUT_DIR, buf, sizeof(buf));
+      if (ret == 0) {
+        memcpy(buf_cmd, "rm -rf ", sizeof(buf_cmd));
+        snprintf(buf_cmd + strlen(buf_cmd), sizeof(buf_cmd) - strlen(buf_cmd) - 1, "rm -rf %s", buf);
+        system(buf_cmd);
+        sleep(WT_TIME);
+
+        statfs(VIDEO_PUT_DIR, &diskInfo);
+
+        blocksize = diskInfo.f_bsize;
+        totalsize = blocksize * diskInfo.f_blocks;
+        availableDisk = diskInfo.f_bavail * blocksize;
+
+        memset(buf, 0x00, sizeof(buf));
+        memset(buf_cmd, 0x00, sizeof(buf_cmd));
+      } else {
+      
+        break;
+      }
+    }
+
+    sleep(WT_MAX_TIME);
+  }
+
+  return NULL;
+}
+
+/*initialize the stream data channel*/
+int proto_AVInit(void) {
+
+  int ret; 
+  int flag;
+  pthread_t tid;
+  struct stat stat_buf;
+
+  if (stat(VIDEO_CONF_DATA, &stat_buf) != 0) {
+    SOAP_DBGERR("The video configuration(%s) is not existed! Please put it firstly!\n", VIDEO_CONF_DATA);
+
+    return -1;
+  }
+
+  ret = chmod(VIDEO_CONF_DATA, 0777);
+  if (ret < 0) {
+    SOAP_DBGERR("parse the configuration error: %s\n", strerror(errno));
+
+    return -1;
+  }
+
+  ret = DiscoverDevice(cb_av_probe);
+  if (ret <= 0) { 
+    return -1;
+  }
+
+  ret = pthread_create(&tid, NULL, task_av_capture, &flag);
+  if (ret) {
+    return -1;
+  }
+
+  ret = pthread_create(&tid, NULL, task_disk_mon, &flag);
+  if (ret) {
+    return -1;
+  }
+
+  return 0;
+}
+
+void proto_AVStart(AVDevs *DevData) {
+  
+  DevData->slice_stat = TRUE;
+ 
+  DevData->run_stat = TRUE;
+
+  sem_post(&(DevData->sem_cap));
+
+}
+ 
+static int av_start_cap(AVDevs *DevData) {
+  int ret;
+  pid_t pid;
+  char data_buf[MAX_BUF_SIZE] = { 0x00 };
+  char temp_buf[MAX_BUF_SIZE] = { 0x00 };
+  char data_buf_temp[MAX_BUF_SIZE] = { 0x00 };
+  char buf[MAX_BUF_SIZE] = { 0x00 };
+
+  signal(SIGINT, handler);
+
+  pid = fork();
+  if (pid < 0) {
+    SOAP_DBGERR("AV start failure: fork failed!\n");
+
+    return -1;
+
+  }
+
+  if (pid > 0) {
+
+    timer_start(gAVDevs->timer_id, gAVDevs->timer_sec);
+
+    while((gAVDevs->run_stat == TRUE) && (gAVDevs->slice_stat == TRUE)) {
+      sleep(1);
+    }
+    timer_stop(gAVDevs->timer_id);
+
+    kill(pid, SIGINT);
+
+    wait(NULL);
+
+    sync();
+
+    if ((gAVDevs->work_mode == PAUSE) && (gAVDevs->pause_enable == FALSE)) {
+     
+      gAVDevs->pause_enable = TRUE;
+
+    } else if ((gAVDevs->work_mode == PAUSE) && (gAVDevs->pause_enable == TRUE)) {
+
+      system_date_get(data_buf_temp, sizeof(data_buf_temp));
+
+      ret = get_dir_with_key(VIDEO_PUT_DIR, gAVDevs->ip, data_buf_temp, data_buf, sizeof(data_buf));
+      if (ret > 0) {
+
+        memcpy(temp_buf, data_buf, sizeof(temp_buf) - 1);
+        memset(data_buf, 0x00, sizeof(data_buf));
+        get_file_with_key(temp_buf, NULL, data_buf, sizeof(data_buf), 0);
+
+        memset(data_buf_temp, 0x00, sizeof(data_buf_temp));
+        get_file_with_key(temp_buf, data_buf, data_buf_temp, sizeof(data_buf_temp), 1); 
+
+        snprintf(buf, sizeof(buf) - 1, "%s", VIDEO_CONF_DATA);
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf) - 1, "%s %s", data_buf_temp, data_buf);
+        system(buf);
+      }
+
+      gAVDevs->work_mode = NORMAL;
+
+      gAVDevs->pause_enable = FALSE;
+    }
+
+  } else {
+
+    ret = video_file_create(data_buf, sizeof(data_buf));
+    if (ret < 0) {
+      return 0;
+    }
+
+    ret = execl(FFMPEG_BIN_DIR, "ffmpeg", "-f", "rtsp", "-rtsp_transport", "tcp", "-i", gAVDevs->uri_data, "-vcodec", "copy", "-y", data_buf, (char *)NULL);
+    if (ret < 0) {
+      SOAP_DBGERR("ffmpeg stuffs are not available: %s\n", strerror(errno));
+      SOAP_DBGERR("please check and confirm it had already been installed correctly!\n");
+    }
+  
+  }
+
+  return 0;
+}
+
+void proto_AVStop(AVDevs *DevData, enum wr_mode mode) {
+
+  DevData->run_stat = FALSE;
+
+  DevData->work_mode = mode;
+}
+
+static int video_file_create(char *data_buf, int length) {
+  
+  int ret;
+  int len;
+  struct stat stat_buf;
+  char buf[MAX_BUF_SIZE] = { 0x00 };
+
+  struct tm tloc;
+  time_t now;
+  time(&now);
+  localtime_r(&now, &tloc);
+
+  if (stat(VIDEO_PUT_DIR, &stat_buf) != 0) {
+    memcpy(buf, "mkdir -p ", sizeof(buf));
+    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf) - 1, "%s", VIDEO_PUT_DIR);
+    system(buf);
+  }
+
+  memset(buf, 0x00, sizeof(buf));
+  len = MAX_BUF_SIZE - 1;
+  snprintf(buf, len, "%s", VIDEO_PUT_DIR);
+  len = (MAX_BUF_SIZE - 1) >= strlen(buf) ? MAX_BUF_SIZE - 1 - strlen(buf) : 0;
+  snprintf(buf + strlen(buf), len, "/%d-", tloc.tm_year + 1900);
+  len = (MAX_BUF_SIZE - 1) >= strlen(buf) ? MAX_BUF_SIZE - 1 - strlen(buf) : 0;
+  snprintf(buf + strlen(buf), len, "%d-", tloc.tm_mon + 1);
+  len = (MAX_BUF_SIZE - 1) >= strlen(buf) ? MAX_BUF_SIZE - 1 - strlen(buf) : 0;
+  snprintf(buf + strlen(buf), len, "%d", tloc.tm_mday);
+  len = (MAX_BUF_SIZE - 1) >= strlen(buf) ? MAX_BUF_SIZE - 1 - strlen(buf) : 0;
+  snprintf(buf + strlen(buf), len, "_%s", gAVDevs->ip);
+
+  if (stat(buf, &stat_buf) != 0) {
+
+    ret = mkdir(buf, 0777);
+    if (ret < 0) {
+      SOAP_DBGERR("the video put dir create failure: %s\n", strerror(errno));
+
+      return -1; 
+    }   
+  }
+
+  time(&now);
+  localtime_r(&now, &tloc);
+  len = (MAX_BUF_SIZE - 1) >= strlen(buf) ? MAX_BUF_SIZE - 1 - strlen(buf) : 0;
+  snprintf(buf + strlen(buf), len, "/%d-", tloc.tm_hour);
+  len = (MAX_BUF_SIZE - 1) >= strlen(buf) ? MAX_BUF_SIZE - 1 - strlen(buf) : 0;
+  snprintf(buf + strlen(buf), len, "%d-", tloc.tm_min);
+  len = (MAX_BUF_SIZE - 1) >= strlen(buf) ? MAX_BUF_SIZE - 1 - strlen(buf) : 0;
+  snprintf(buf + strlen(buf), len, "%d.mp4", tloc.tm_sec);
+
+  memcpy(data_buf, buf, length);
+
+  return 0;
+}
+
+static void system_date_get(char *buf, int len) 
+{
+  struct tm tloc;
+  time_t now;
+  time(&now);
+  localtime_r(&now, &tloc);
+
+  sprintf(buf, "%d", tloc.tm_year + 1900);
+  sprintf(buf + strlen(buf), "-%d", tloc.tm_mon + 1);
+  sprintf(buf + strlen(buf), "-%d", tloc.tm_mday);
+
+  return;
+}
+
+static void cb_av_probe(char *DeviceXAddr)
+{
+  int ret;
+  int len;
+  char *pos_s, *pos_e;
+
+  if (gAVDevs == NULL) {
+
+    gAVDevs = malloc(sizeof(AVDevs));
+
+    SOAP_ASSERT(gAVDevs != NULL);
+    
+    memset(gAVDevs, 0x00, sizeof(AVDevs));
+
+    pos_s = strstr(DeviceXAddr, ADDR_PREFIX);
+    pos_e = strstr(DeviceXAddr + strlen(ADDR_PREFIX), ADDR_LAST);
+    len = pos_e - DeviceXAddr - strlen(ADDR_PREFIX);
+    memcpy(gAVDevs->ip, DeviceXAddr + strlen(ADDR_PREFIX), len);
+
+    gAVDevs->timer_sec = VIDEO_DURATION;
+    
+    gAVDevs->dev_stat = ENABLE;
+    gAVDevs->run_stat = FALSE;
+
+    ret = sem_init(&(gAVDevs->sem_cap), 0, 0);
+    SOAP_ASSERT(ret == 0);
+
+    timer_init(&(gAVDevs->timer_id), av_timer_handler);
+  }
+
+  /*Get the device capabilities*/
+  proto_GetCapabilities(DeviceXAddr, &(gAVDevs->capa), USERNAME, PASSWORD);
+
+  /*Parse the stream configurations*/
+  proto_GetProfiles(gAVDevs->capa.MediaXAddr, &(gAVDevs->profiles), USERNAME, PASSWORD);
+  
+  proto_GetStreamUri(gAVDevs->capa.MediaXAddr, gAVDevs->profiles->token, gAVDevs->uri, sizeof(gAVDevs->uri), USERNAME, PASSWORD);
+
+  bridge_uri(gAVDevs->uri, USERNAME, PASSWORD, gAVDevs->uri_data, sizeof(gAVDevs->uri_data));
+
+}
+
+AVDevs *proto_AVGethandle(void) 
+{
+  return gAVDevs;
+}
+
+void proto_AVClose(void) 
+{
+  if (gAVDevs != NULL) {
+
+    if (gAVDevs->dev_stat == ENABLE) {
+      proto_AVStop(gAVDevs, NORMAL);
+    }    
+
+    gAVDevs->dev_stat = DISABLE;
+
+    while(gAVDevs->proc_stat != DISABLE) {
+      sleep(2);
+    }
+
+    sem_destroy(&(gAVDevs->sem_cap));
+
+    timer_destroy(gAVDevs->timer_id);
+
+    free(gAVDevs->profiles);
+
+    free(gAVDevs);
+
+    gAVDevs = NULL;
+  }
+}
+
+/*get the video and audio packet*/
+void get_stream(AVDevs *DevData)
+{
+  unsigned int    i;
+  int             ret;
+  int             video_st_index = -1;
+  int             audio_st_index = -1;
+  AVFormatContext *ifmt_ctx = NULL;
+  AVPacket        pkt;
+  AVStream        *st = NULL;
+  char            errbuf[64];
+
+  /*Open the input file for reading*/
+  if ((ret = avformat_open_input(&ifmt_ctx, DevData->uri_data, 0, NULL)) < 0) {
+    SOAP_DBGERR("Could not open input file '%s' (error '%s')\n", DevData->uri_data, av_make_error_string(errbuf, sizeof(errbuf), ret));
+    
+    goto EXIT;
+  }
+
+  /*Get information on the input file (number of streams etc.))*/
+  if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
+    SOAP_DBGERR("Could not open find stream info (error '%s')\n", av_make_error_string(errbuf, sizeof(errbuf), ret));
+        
+    goto EXIT;
+  }
+
+  for (i = 0; i < ifmt_ctx->nb_streams; i++) {
+    av_dump_format(ifmt_ctx, i, DevData->uri_data, 0);
+  }
+
+  /*find video stream index*/
+  for (i = 0; i < ifmt_ctx->nb_streams; i++) {
+        
+    st = ifmt_ctx->streams[i];
+
+    switch(st->codec->codec_type) {
+      
+      case AVMEDIA_TYPE_AUDIO: 
+        audio_st_index = i; 
+
+        break;
+    
+      case AVMEDIA_TYPE_VIDEO: 
+        video_st_index = i; 
+
+        break;
+      
+      default: 
+        break;
+    }
+  }
+    
+  if (-1 == video_st_index) {
+    SOAP_DBGERR("No H.264 video stream in the input file\n");
+        
+    goto EXIT;
+  }
+
+  /*initialize packet*/
+  av_init_packet(&pkt);
+  pkt.data = NULL;
+  pkt.size = 0;
+
+  while (1) {
+    do {
+      
+      ret = av_read_frame(ifmt_ctx, &pkt);
+
+    } while (ret == AVERROR(EAGAIN));
+
+    if (ret < 0) {
+      SOAP_DBGERR("Could not read frame (error '%s')\n", av_make_error_string(errbuf, sizeof(errbuf), ret));
+      
+      break;
+    }
+
+    /*video frame*/
+    if (pkt.stream_index == video_st_index) {
+      
+      SOAP_DBGERR("Video Packet size = %d\n", pkt.size);
+        
+    } else if(pkt.stream_index == audio_st_index) {
+      /*audio frame*/
+      SOAP_DBGERR("Audio Packet size = %d\n", pkt.size);
+
+    } else {
+
+      SOAP_DBGERR("Unknow Packet size = %d\n", pkt.size);
+    
+    }
+
+    av_packet_unref(&pkt);
+  }
+
+EXIT:
+
+  if (NULL != ifmt_ctx) {
+    
+    avformat_close_input(&ifmt_ctx);
+    
+    ifmt_ctx = NULL;
+  }
+
+  return ;
+}
+
+/*Get the device service stream address*/
+int proto_GetStreamUri(const char *MediaXAddr, char *ProfileToken, char *uri, unsigned int sizeuri, const char *username, const char *passwd)
+{
+
+  int result = 0;
+  struct soap *soap = NULL;
+  struct tt__StreamSetup              ttStreamSetup;
+  struct tt__Transport                ttTransport;
+  struct _trt__GetStreamUri           req;
+  struct _trt__GetStreamUriResponse   rep;
+
+  SOAP_ASSERT(NULL != MediaXAddr);
+  SOAP_ASSERT(NULL != uri);
+  
+  memset(uri, 0x00, sizeuri);
+
+  SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
+
+  memset(&req, 0x00, sizeof(req));
+  memset(&rep, 0x00, sizeof(rep));
+  memset(&ttStreamSetup, 0x00, sizeof(ttStreamSetup));
+  memset(&ttTransport, 0x00, sizeof(ttTransport));
+    
+  ttStreamSetup.Stream                = tt__StreamType__RTP_Unicast;
+  ttStreamSetup.Transport             = &ttTransport;
+  ttStreamSetup.Transport->Protocol   = tt__TransportProtocol__RTSP;
+  ttStreamSetup.Transport->Tunnel     = NULL;
+  req.StreamSetup                     = &ttStreamSetup;
+  req.ProfileToken                    = ProfileToken;
+
+  proto_SetAuthInfo(soap, username, passwd);
+  result = soap_call___trt__GetStreamUri(soap, MediaXAddr, NULL, &req, &rep);
+  SOAP_CHECK_ERROR(result, soap, "GetServices");
+
+  dump_trt__GetStreamUriResponse(&rep);
+
+  result = -1;
+  if (NULL != rep.MediaUri) {
+    if (NULL != rep.MediaUri->Uri) {
+      if (sizeuri > strlen(rep.MediaUri->Uri)) {
+        
+        strcpy(uri, rep.MediaUri->Uri);
+        
+        result = 0;
+      } else {
+        SOAP_DBGERR("Not enough cache!\n");
+      }
+    }
+  }
+
+EXIT:
+
+  if (NULL != soap) {
+    proto_soap_delete(soap);
+  }
+
+  return result;
+
+}
+
+
diff --git a/service/av_demux/av_demux.h b/service/av_demux/av_demux.h
new file mode 100644
index 0000000..e8de362
--- /dev/null
+++ b/service/av_demux/av_demux.h
@@ -0,0 +1,100 @@
+#ifndef __SRV_AV_DEMUX_H__
+#define __SRV_AV_DEMUX_H__
+
+#include <semaphore.h>
+#include <pthread.h>
+
+#include "capabilities/capa.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VIDEO_PUT_DIR "/home/Work/Log_repo/video_log"
+#define VIDEO_CONF_DATA "/usr/bin/video_conv.sh"
+#define FFMPEG_BIN_DIR "/home/Work/Sources_temp/ffmpeg_sources/host/bin/ffmpeg"
+
+#define VIDEO_DURATION    (5 * 60) //sec
+
+#define KB (1024.0)
+#define MB (KB * 1024.0)
+#define GB (MB * 1024.0)
+#define DISK_FREE_THRES   (0.05)
+
+/*the player work mode status*/
+enum wr_mode {
+  NORMAL,
+  PAUSE,
+};
+
+/*playback mode set key*/
+typedef struct _playback_key {
+
+  /*format: 192.168.1.101*/
+  char name[PTOTO_ADDRESS_ADD];
+
+  /*format: 2022-6-28*/
+  char date[PTOTO_ADDRESS_ADD];
+
+  /*format: 21-32-19*/
+  char time[PTOTO_ADDRESS_ADD];
+
+} playback_key;
+
+/*the operational handle*/
+typedef struct _AVDevs {
+
+  /*the devices capabilities*/
+  struct tagCapabilities capa;
+
+  /*the profies for each servies*/
+  struct tagProfile *profiles;
+
+  timer_t timer_id;
+  int timer_sec;
+
+  sem_t sem_cap;
+
+  volatile char run_stat;
+  volatile char slice_stat;
+
+  char ip[PROTO_ADDRESS_SIZE];
+
+  char uri[PROTO_ADDRESS_SIZE + PTOTO_ADDRESS_ADD];
+  char uri_data[PROTO_ADDRESS_SIZE + PTOTO_ADDRESS_ADD];
+
+  /*the device work stat*/
+  char dev_stat;
+
+  /*the process work stat*/
+  char proc_stat;
+
+  /*the stat record for pause work mode*/
+  char pause_enable;
+  char pause_prev_loc[MAX_BUF_SIZE];
+  char pause_cur_loc[MAX_BUF_SIZE];
+
+  enum wr_mode work_mode;
+
+} AVDevs;
+
+int proto_AVInit(void);
+void proto_AVStart(AVDevs *DevData);
+void proto_AVStop(AVDevs *DevData, enum wr_mode mode);
+void proto_AVClose(void);
+AVDevs *proto_AVGethandle(void);
+void get_stream(AVDevs *DevData);
+int playback_get_key(playback_key set, char *buf, int length);
+
+static int get_dir_with_key(char *dir_path, char *name, char *key, char *buf, int length);
+static int get_file_with_key(char *dir_path, char *key, char *buf, int length, int flag);
+static int get_dir_oldest(char *dir_path, char *buf, int length);
+
+static void cb_av_probe(char *DeviceXAddr);
+static int video_file_create(char *buf, int len);
+static int av_start_cap(AVDevs *DevData);
+
+static void system_date_get(char *buf, int len);
+
+#endif 
+
diff --git a/service/av_demux/video_conv.sh b/service/av_demux/video_conv.sh
new file mode 100644
index 0000000..f822601
--- /dev/null
+++ b/service/av_demux/video_conv.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+exist_file()
+{
+  if [ -e "$1" ]
+  then
+    return 1
+  else
+    return 2
+  fi  
+}
+
+if [ $# != 2 ] ; then
+echo "USAGE: $0 media_src1 media_src2"
+exit 1;
+fi
+
+arg1=`basename $1`
+
+arg2=`basename $2`
+
+mainN1=${arg1%%.*}
+mainE=${arg1#*.}
+mainN2=${arg2%%.*}
+
+dirname=`dirname $1`
+
+exist_file $1
+value=$?
+
+if [ $value -eq 2 ] 
+then 
+  echo "No source media ${arg1} found in the directory! Put it here firstly!\n"
+  exit
+fi
+
+exist_file $2
+value=$?
+
+if [ $value -eq 2 ] 
+then 
+  echo "No source media ${arg2} found in the directory! Put it here firstly!\n"
+  exit
+fi
+
+output1=${mainN1}.ts
+output2=${mainN2}.ts
+
+ffmpeg -i $1 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ${output1}
+ffmpeg -i $2 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ${output2}
+ffmpeg -i "concat:${output1}|${output2}" -acodec copy -vcodec copy -absf aac_adtstoasc ${mainN1}.${mainE}
+
+rm -rf ${output1}
+rm -rf ${output2}
+rm -rf $1
+mv ${mainN1}.${mainE} ${dirname}
+
+
diff --git a/service/capabilities/capa.c b/service/capabilities/capa.c
index fd2033f..6fc0847 100644
--- a/service/capabilities/capa.c
+++ b/service/capabilities/capa.c
@@ -87,6 +87,49 @@
     return rep.__sizeProfiles;
 }
 
+int proto_GetVideoSource(const char *DeviceXAddr, char *buf, int len, const char *username, const char *passwd) {
+    int result = 0;
+    struct soap *soap = NULL;
+    struct _trt__GetVideoSources *getVideoSources;
+    struct _trt__GetVideoSourcesResponse *getVideoSourcesRes;
+
+    SOAP_ASSERT(NULL != DeviceXAddr);
+    SOAP_ASSERT(NULL != buf);
+    SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
+
+    getVideoSources = soap_new__trt__GetVideoSources(soap, 1);
+    getVideoSourcesRes = soap_new__trt__GetVideoSourcesResponse(soap, 1);
+
+    proto_SetAuthInfo(soap, username, passwd);
+
+    result = soap_call___trt__GetVideoSources(soap, DeviceXAddr, NULL, getVideoSources, getVideoSourcesRes);
+    SOAP_CHECK_ERROR(result, soap, "GetVideoSourc");
+
+    if (getVideoSourcesRes->__sizeVideoSources <= 0) {
+      
+      result = SOAP_NO_DATA;
+      SOAP_CHECK_ERROR(result, soap, "GetVideoSourc");
+
+    } else {
+
+      for (int i = 0; i < getVideoSourcesRes->__sizeVideoSources; i++) {
+
+        log_level_val(0, "get video source token: ", log_str, getVideoSourcesRes->VideoSources[i].token);
+
+        if (i == 0) {
+          strncpy(buf, getVideoSourcesRes->VideoSources[i].token, len);
+        }
+      }
+    }
+
+EXIT:
+    if (NULL != soap) {
+        proto_soap_delete(soap);
+    }
+
+    return result;
+}
+
 int proto_GetCapabilities(const char *DeviceXAddr, struct tagCapabilities *capa, const char *username, const char *passwd)
 {
     int result = 0;
diff --git a/service/ptz/ptz.c b/service/ptz/ptz.c
index c7991f0..5921a42 100644
--- a/service/ptz/ptz.c
+++ b/service/ptz/ptz.c
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <semaphore.h>
+#include <string.h>
 #include <pthread.h>
 #include <signal.h>
 #include <errno.h>
@@ -22,9 +23,9 @@
   int ret; 
 
   SOAP_ASSERT(DevData != NULL);
-  SOAP_ASSERT(DevData->profilesToken != NULL);
+  SOAP_ASSERT(DevData->profiles != NULL);
 
-  ret = DevData->profilesToken->venc.Width;
+  ret = DevData->profiles->venc.Width;
 
   return ret;
 }
@@ -35,14 +36,17 @@
   int ret;
 
   SOAP_ASSERT(DevData != NULL);
-  SOAP_ASSERT(DevData->profilesToken != NULL);
+  SOAP_ASSERT(DevData->profiles != NULL);
 
-  ret = DevData->profilesToken->venc.Height;
+  ret = DevData->profiles->venc.Height;
 
   return ret;
 }
 
 static void cb_probe(char *DeviceXAddr) {
+
+  int len;
+  char *pos_s, *pos_e;
 
   if (gPtzDevs == NULL) {
 
@@ -51,10 +55,15 @@
     SOAP_ASSERT(gPtzDevs != NULL);
 
     memset(gPtzDevs, 0x00, sizeof(PtzDevs));
+
+    pos_s = strstr(DeviceXAddr, ADDR_PREFIX);
+    pos_e = strstr(DeviceXAddr + strlen(ADDR_PREFIX), ADDR_LAST);
+    len = pos_e - DeviceXAddr - strlen(ADDR_PREFIX);
+    memcpy(gPtzDevs->ip, DeviceXAddr + strlen(ADDR_PREFIX), len);
   }
 
   proto_GetCapabilities(DeviceXAddr, &(gPtzDevs->capa), USERNAME, PASSWORD);
-  proto_GetProfiles(gPtzDevs->capa.MediaXAddr, &(gPtzDevs->profilesToken), USERNAME, PASSWORD);
+  proto_GetProfiles(gPtzDevs->capa.MediaXAddr, &(gPtzDevs->profiles), USERNAME, PASSWORD);
 
 }
 
@@ -76,7 +85,7 @@
     ret = sem_init(&(gPtzDevs->sem_tour), 0, 0);
     SOAP_ASSERT(ret == 0);
 
-    timer_init(&(gPtzDevs->timer_id));
+    timer_init(&(gPtzDevs->timer_id), ptz_timer_handler);
 
     gPtzDevs->dev_stat = DISABLE;
     pthread_mutex_init(&(gPtzDevs->node_mutex), NULL);
@@ -93,7 +102,7 @@
 
         timer_destroy(gPtzDevs->timer_id);
 
-        free(gPtzDevs->profilesToken);
+        free(gPtzDevs->profiles);
 
         free(gPtzDevs);
 
@@ -194,70 +203,20 @@
 }
 
 /*the timer process heandler*/
-static void timer_handler(union sigval para) {
+void ptz_timer_handler(union sigval para) {
 
   if (gPtzDevs != NULL) {
+
+    pthread_mutex_lock(&(gPtzDevs->node_mutex));
 
     gPtzDevs->wt_stat = DISABLE;
 
     pthread_cond_signal(&(gPtzDevs->cond));
+
+    pthread_mutex_unlock(&(gPtzDevs->node_mutex));
   }
 
   return;
-}
-
-static int timer_init(timer_t *timer_index) {
-  struct sigevent event;
-  timer_t timer;
-  int ret;
-
-  memset(&event, 0x00, sizeof(event));
-  event.sigev_value.sival_int = ENABLE;
-  event.sigev_value.sival_ptr = NULL;
-  event.sigev_notify = SIGEV_THREAD;
-  event.sigev_notify_function = timer_handler;
-  
-  ret = timer_create(CLOCK_REALTIME, &event, &timer);
-  if (ret) {
-    return -1;
-  }
-
-  if (timer_index != NULL) {
-    *timer_index = timer;
-  }
-
-  return 0;
-}
-
-static int timer_start(timer_t timer_index, int sec) {
-  int ret;
-  struct itimerspec ts;
-
-  ts.it_interval.tv_sec = 0;
-  ts.it_interval.tv_nsec = 0;
-  ts.it_value.tv_sec = sec;
-  ts.it_value.tv_nsec = 0;
-  ret = timer_settime(timer_index, 0, &ts, NULL);
-  if (ret) {
-    return -1;
-  }
-
-  return ret;
-}
-
-static int timer_stop(timer_t timer_index) {
-
-  int ret = timer_start(timer_index, 0);
-
-  return ret;
-}
-
-static int timer_destroy(timer_t timer_index) {
-  int ret;
-
-  ret = timer_delete(timer_index);
-    
-  return ret;
 }
 
 /*initialize the PTZ*/
@@ -355,7 +314,7 @@
   struct _tptz__GetStatusResponse   *getStatusResponse = NULL;
 
   SOAP_ASSERT(DevData != NULL);
-  SOAP_ASSERT(NULL != DevData->profilesToken);
+  SOAP_ASSERT(NULL != DevData->profiles);
   SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
 
   getStatus = soap_new__tptz__GetStatus(soap, 1);
@@ -364,7 +323,7 @@
   strncpy(PTZXAddr, DevData->capa.PTZXAddr, PROTO_ADDRESS_SIZE);
   proto_SetAuthInfo(soap, username, passwd);
 
-  getStatus->ProfileToken = DevData->profilesToken->token;
+  getStatus->ProfileToken = DevData->profiles->token;
   result = soap_call___tptz__GetStatus(soap, PTZXAddr, NULL, getStatus, getStatusResponse);
   SOAP_CHECK_ERROR(result, soap, "proto_PTZ_GetStatus");
 
@@ -614,7 +573,7 @@
     char PTZXAddr[PROTO_ADDRESS_SIZE] = { 0x00 };
 
     SOAP_ASSERT(DevData != NULL);
-    SOAP_ASSERT(NULL != DevData->profilesToken);
+    SOAP_ASSERT(NULL != DevData->profiles);
     SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
 
     proto_PTZ_GetStatus(DevData, &pos_get, username, passwd);
@@ -628,7 +587,7 @@
 
     strncpy(PTZXAddr, DevData->capa.PTZXAddr, PROTO_ADDRESS_SIZE);
     proto_SetAuthInfo(soap, username, passwd);
-    absMove->ProfileToken = DevData->profilesToken->token;
+    absMove->ProfileToken = DevData->profiles->token;
 
     absMove->Position = soap_new_tt__PTZVector(soap, 1);
     absMove->Position->PanTilt = soap_new_tt__Vector2D(soap, 1);
@@ -660,7 +619,7 @@
     enum xsd__boolean xsd_false = xsd__boolean__false_;
   
     SOAP_ASSERT(DevData != NULL);
-    SOAP_ASSERT(NULL != DevData->profilesToken);
+    SOAP_ASSERT(NULL != DevData->profiles);
     SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
 
     struct _tptz__Stop *tptzStop = soap_new__tptz__Stop(soap, 1);
@@ -668,7 +627,7 @@
 
     strncpy(PTZXAddr, DevData->capa.PTZXAddr, PROTO_ADDRESS_SIZE);
     proto_SetAuthInfo(soap, username, passwd);
-    tptzStop->ProfileToken = DevData->profilesToken->token;
+    tptzStop->ProfileToken = DevData->profiles->token;
 
     tptzStop->PanTilt = &xsd_true;
     tptzStop->Zoom = &xsd_false;
@@ -693,7 +652,7 @@
     char PTZXAddr[PROTO_ADDRESS_SIZE] = { 0x00 };
 
     SOAP_ASSERT(DevData != NULL);
-    SOAP_ASSERT(NULL != DevData->profilesToken);
+    SOAP_ASSERT(NULL != DevData->profiles);
     SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
     
     struct _tptz__ContinuousMove* contMove = soap_new__tptz__ContinuousMove(soap, 1);
@@ -705,7 +664,7 @@
 
     strncpy(PTZXAddr, DevData->capa.PTZXAddr, PROTO_ADDRESS_SIZE);
     proto_SetAuthInfo(soap, username, passwd);
-    contMove->ProfileToken = DevData->profilesToken->token;
+    contMove->ProfileToken = DevData->profiles->token;
     contMove->Velocity = soap_new_tt__PTZSpeed(soap, 1);
     memset(contMove->Velocity, 0x00, sizeof(struct tt__PTZSpeed));
     contMove->Velocity->PanTilt = soap_new_tt__Vector2D(soap, 1);
@@ -863,7 +822,7 @@
     char PTZXAddr[PROTO_ADDRESS_SIZE] = { 0x00 };
 
     SOAP_ASSERT(DevData != NULL);
-    SOAP_ASSERT(NULL != DevData->profilesToken);
+    SOAP_ASSERT(NULL != DevData->profiles);
     SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
 
     pos_p = para_check(pos_p);
@@ -875,7 +834,7 @@
 
     strncpy(PTZXAddr, DevData->capa.PTZXAddr, PROTO_ADDRESS_SIZE);
     proto_SetAuthInfo(soap, username, passwd);
-    relMove->ProfileToken = DevData->profilesToken->token;
+    relMove->ProfileToken = DevData->profiles->token;
     relMove->Translation = (struct tt__PTZVector *)soap_malloc(soap, sizeof(struct tt__PTZVector));
     memset(relMove->Translation, 0x00, sizeof(struct tt__PTZVector));
     relMove->Translation->PanTilt = soap_new_tt__Vector2D(soap, 1);
@@ -953,7 +912,7 @@
 }
 
 /*set the focus-on functionality*/
-int proto_PTZ_ImagingSet(PtzDevs *DevData, float speed, const char *username, const char *passwd) {
+int proto_PTZ_ImagingSet(PtzDevs *DevData, enum PTZCMD cmd, float speed, const char *username, const char *passwd) {
   int result = 0;
   float speed_val;
   struct soap *soap = NULL;
@@ -961,34 +920,61 @@
   struct tt__ContinuousFocus *stContFocus = NULL;
   struct _timg__Move *stMoveReq = NULL;
   struct _timg__MoveResponse *stMoveRes = NULL;
+  struct _timg__Stop *stStopReq = NULL;
+  struct _timg__StopResponse *stStopRes = NULL;
 
   SOAP_ASSERT(NULL != DevData);
-  SOAP_ASSERT(NULL != DevData->profilesToken);
+  SOAP_ASSERT(NULL != DevData->profiles);
   SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
   
   stFocusMove = soap_new_tt__FocusMove(soap, 1);
   stContFocus = soap_new_tt__ContinuousFocus(soap, 1);
-  
-  proto_SetAuthInfo(soap, username, passwd);
-
+ 
   stMoveReq = soap_new__timg__Move(soap, 1);
   stMoveRes = soap_new__timg__MoveResponse(soap, 1);
+
+  stStopReq = soap_new__timg__Stop(soap, 1);
+  stStopRes = soap_new__timg__StopResponse(soap, 1);
   
   memset(stMoveReq, 0x00, sizeof(struct _timg__Move));
   memset(stMoveRes, 0x00, sizeof(struct _timg__MoveResponse));
   
-  speed_val = pos_res_z(speed);
+  memset(stStopReq, 0x00, sizeof(struct _timg__Stop));
+  memset(stStopRes, 0x00, sizeof(struct _timg__StopResponse));
 
-  stContFocus->Speed = speed_val;
+  stMoveReq->Focus = stFocusMove;
+  stMoveReq->Focus->Continuous = stContFocus;
+
+  stMoveReq->VideoSourceToken = DevData->profiles->videoCfg.sourceToken;
+  stStopReq->VideoSourceToken = DevData->profiles->videoCfg.sourceToken;
+
+  proto_SetAuthInfo(soap, username, passwd);
+
+  speed_val = pos_res_z(speed);
+  switch(cmd) {
+    case PTZ_CMD_FOCUS_IN:
+      stContFocus->Speed = speed_val;    
+      
+      break;
+
+    case PTZ_CMD_FOCUS_OUT:
+      stContFocus->Speed = speed_val * (-1);
+      
+      break;
+
+    default:
+      result = soap_call___timg__Stop(soap, DevData->capa.MediaXAddr, NULL, stStopReq, stStopRes);
+      SOAP_CHECK_ERROR(result, soap, "proto_PTZ_ImagingSet");
+      
+      break;
+  }
+
   stFocusMove->Continuous = stContFocus;
   stFocusMove->Absolute = NULL;
   stFocusMove->Relative = NULL;
 
-  stMoveReq->Focus = stFocusMove;
-  stMoveReq->VideoSourceToken = DevData->profilesToken->videoCfg.token;
-
-  result = soap_call___timg__Move(soap, DevData->profilesToken->token, NULL, stMoveReq, stMoveRes);
-  SOAP_CHECK_ERROR(result, soap, "proto_PTZ_FocusSet");
+  result = soap_call___timg__Move(soap, DevData->capa.MediaXAddr, NULL, stMoveReq, stMoveRes);
+  SOAP_CHECK_ERROR(result, soap, "proto_PTZ_ImagingSet");
   
 EXIT:
     if (NULL != soap) {
@@ -1007,7 +993,7 @@
   char PTZXAddr[PROTO_ADDRESS_SIZE] = { 0x00 };
 
   SOAP_ASSERT(DevData != NULL);
-  SOAP_ASSERT(NULL != DevData->profilesToken);
+  SOAP_ASSERT(NULL != DevData->profiles);
   SOAP_ASSERT(NULL != (soap = proto_soap_new(SOAP_SOCK_TIMEOUT)));
 
   strncpy(PTZXAddr, DevData->capa.PTZXAddr, PROTO_ADDRESS_SIZE);
@@ -1020,7 +1006,7 @@
     memset(setPreset, 0x00, sizeof(struct _tptz__SetPreset));
     memset(setPresetRes, 0x00, sizeof(struct _tptz__SetPresetResponse));
 
-    setPreset->ProfileToken = DevData->profilesToken->token;
+    setPreset->ProfileToken = DevData->profiles->token;
     if (posName != NULL) {
       setPreset->PresetName = (char *)posName;
     }
@@ -1039,7 +1025,7 @@
     memset(getPresets, 0x00, sizeof(struct _tptz__GetPresets));
     memset(getPresetsRes, 0x00, sizeof(struct _tptz__GetPresetsResponse));
 
-    getPresets->ProfileToken = DevData->profilesToken->token;
+    getPresets->ProfileToken = DevData->profiles->token;
 
     result = soap_call___tptz__GetPresets(soap, PTZXAddr, NULL, getPresets, getPresetsRes);
     SOAP_CHECK_ERROR(result, soap, "proto_PTZPreset");
@@ -1055,7 +1041,7 @@
     memset(gotoPreset, 0x00, sizeof(struct _tptz__GotoPreset));
     memset(gotoPresetRes, 0x00, sizeof(struct _tptz__GotoPresetResponse));
 
-    gotoPreset->ProfileToken = DevData->profilesToken->token;
+    gotoPreset->ProfileToken = DevData->profiles->token;
 
     if (posToken != NULL) {
       sprintf(buf, "%d", *posToken);
@@ -1072,7 +1058,7 @@
     memset(rmPreset, 0x00, sizeof(struct _tptz__RemovePreset));
     memset(rmPresetRes, 0x00, sizeof(struct _tptz__RemovePresetResponse));
 
-    rmPreset->ProfileToken = DevData->profilesToken->token;
+    rmPreset->ProfileToken = DevData->profiles->token;
     if (posToken != NULL) {
       sprintf(buf, "%d", *posToken);
       rmPreset->PresetToken = buf;
diff --git a/service/ptz/ptz.h b/service/ptz/ptz.h
index 37e0894..6071030 100644
--- a/service/ptz/ptz.h
+++ b/service/ptz/ptz.h
@@ -10,9 +10,6 @@
 
 #include "capabilities/capa.h"
 
-#define USERNAME        "On_admin"                                                
-#define PASSWORD        "a12345678"
-
 #define HK_IDS_2DE      1
 
 #if defined(HK_IDS_2DE)
@@ -44,9 +41,6 @@
 #define MIN_TOUR_TIME   15
 #define MIN_TOUR_POS    2
 
-#define WT_TIME         5
-#define STOP_WT_TIME    3
-
 #define MAX_IMG_SCALE   0.5
 
 #define PI              3.14159
@@ -60,9 +54,6 @@
 #define COEF_FV_A       0.953
 #define COEF_FV_B       0.598
 #define COEF_FV_C       0.166
-
-#define ENABLE          0
-#define DISABLE         1
 
 /*PTZ working stat*/
 enum PTZStat {
@@ -95,6 +86,9 @@
   PTZ_CMD_RIGHTDOWN,
   PTZ_CMD_ZOOM_IN,
   PTZ_CMD_ZOOM_OUT,
+  PTZ_CMD_FOCUS_IN,
+  PTZ_CMD_FOCUS_OUT,
+  PTZ_CMD_FOCUS_STOP,
 };
 
 /*the tradditional preset control command*/
@@ -143,7 +137,7 @@
 
   struct tagCapabilities capa;
 
-  struct tagProfile *profilesToken;
+  struct tagProfile *profiles;
 
   PresetToure_node *posNode;
   int posNode_count;
@@ -166,6 +160,8 @@
 
   /*the touring process work stat*/
   char proc_stat;
+
+  char ip[PROTO_ADDRESS_SIZE];
 
   enum tourType tour_type;
 
@@ -199,7 +195,7 @@
 
 int proto_PTZPreset(PtzDevs *DevData, const char *posName, enum PreSetCMD cmd, \
                       int *posToken, const char *username, const char *passwd);
-int proto_PTZ_ImagingSet(PtzDevs *DevData, float speed, const char *username, const char *passwd);
+int proto_PTZ_ImagingSet(PtzDevs *DevData, enum PTZCMD cmd, float speed, const char *username, const char *passwd);
 
 static void *task_preset_touring(void *arg);
 float proto_PTZZoom_get(PtzDevs *DevData, int x0, int y0, int x1, int y1); 
@@ -209,11 +205,7 @@
 void proto_PTZWaitStopped(PtzDevs *DevData, const char *username, const char *passwd);
 void proto_PTZPreset_tour_stop(PtzDevs *DevData);
 
-static void timer_handler(union sigval para);
-static int timer_init(timer_t *timer_index);
-static int timer_start(timer_t timer_index, int sec);
-static int timer_stop(timer_t timer_index);
-static int timer_destroy(timer_t timer_index);
+static void ptz_timer_handler(union sigval para);
 
 #ifdef __cplusplus
 }
diff --git a/test/Makefile.inc b/test/Makefile.inc
index e9c20a2..75bb0e3 100644
--- a/test/Makefile.inc
+++ b/test/Makefile.inc
@@ -27,15 +27,20 @@
 OBJECTS_ONVIF := $(patsubst %.c,$(TEMPDIR)%.o,$(filter %.c, $(SOURCES_CORE)))
 OBJECTS_COMM  := $(patsubst %.c,$(TEMPDIR)%.o,$(filter %.c, $(SOURCES_COMM)))
 
+FFMPEG_DIR = ../../thirdparty/ffmpeg
 OPENSSL_DIR = ../../thirdparty/openssl
 
 #
 INCLUDE += -I../../core/                               \
            -I../../comm/         \
+           -I$(FFMPEG_DIR)/include          \
            -I$(OPENSSL_DIR)/include
 CFLAGS += $(INCLUDE)
 
+LDFLAGS += -L$(FFMPEG_DIR)/lib
 LDFLAGS += -L$(OPENSSL_DIR)/lib
+LDLIBS += -lavcodec -lavdevice -lavfilter -lavformat \
+           -lavutil -lswresample -lswscale
 LDLIBS += -lcrypto -lssl -lpthread -ldl
 
 %.o: %.cpp
diff --git a/test/av_test/Makefile b/test/av_test/Makefile
new file mode 100644
index 0000000..33ba199
--- /dev/null
+++ b/test/av_test/Makefile
@@ -0,0 +1,52 @@
+CC           := gcc
+CPP          := g++ 
+LD           := ld
+AR           := ar
+STRIP        := strip
+RM           := rm
+
+PROGRAM = av_stream_test
+
+SOURCES += av_test.c
+
+CFLAGS += -Wall -DWITH_DOM -DWITH_NONAMESPACES -DWITH_OPENSSL -Wno-unused
+
+OBJECTS := $(patsubst %.c,$(TEMPDIR)%.o,$(filter %.c, $(SOURCES)))
+
+%.o: %.cpp
+	@echo "  CPP     " $@; 
+	@$(CPP) $(CFLAGS) -c -o $@ $<
+
+%.o: %.c 
+	@echo "  CC      " $@; 
+	@$(CC) $(CFLAGS) -c -o $@ $<
+
+FFMPEG_DIR = ../../thirdparty/ffmpeg
+OPENSSL_DIR = ../../thirdparty/openss
+
+LDFLAGS += -L$(FFMPEG_DIR)/lib
+LDFLAGS += -L$(OPENSSL_DIR)/lib
+LDFLAGS += -L../../
+LDLIBS += -lonvif_std
+LDLIBS += -lavcodec -lavdevice -lavfilter -lavformat \
+           -lavutil -lswresample -lswscale
+LDLIBS += -lcrypto -lssl -lpthread -ldl -lrt
+LDLIBS +=  -lprotobuf -lprotobuf-lite
+
+INCLUDE += -I../../core/                               \
+           -I../../comm/         \
+           -I../../service      \
+           -I$(FFMPEG_DIR)/include          \
+           -I$(OPENSSL_DIR)/include
+CFLAGS += $(INCLUDE)
+
+all: $(OBJECTS)
+	$(CC) -o $(PROGRAM) $(OBJECTS) $(LDFLAGS) $(LDLIBS) $(CFLAGS)
+
+clean:
+	$(RM) -f $(OBJECTS)
+	$(RM) -f $(PROGRAM)
+
+allclean: clean
+	$(RM) -f $(OBJECTS_ONVIF)
+
diff --git a/test/av_test/av_test.c b/test/av_test/av_test.c
new file mode 100644
index 0000000..7f4e660
--- /dev/null
+++ b/test/av_test/av_test.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "PTZBinding.nsmap"
+#include "av_demux/av_demux.h"
+
+int main(int argc, char **argv)
+{
+  int ret;
+  char parse_buf[MAX_BUF_SIZE] = { 0x00 };
+  playback_key data_set = {"192.168.1.101", "2022-7-3", "21-52-16"};
+  AVDevs *handle = NULL;
+
+  ret = proto_AVInit();
+  if (ret < 0) {
+    printf("AV stream initialization failure!\n");
+
+    return 0;
+  }
+
+  printf("start the av stream:\n");
+  handle = proto_AVGethandle();
+  proto_AVStart(handle);
+ 
+  sleep(5 * 60 * 2);
+
+  printf("stop the av stream now:\n");
+  proto_AVStop(handle, NORMAL);
+
+  sleep(3);
+
+  printf("re-start the AV now:\n");
+  proto_AVStart(handle);
+
+  sleep(120);
+
+  printf("pause the av stream now:\n");
+  proto_AVStop(handle, PAUSE);
+
+  sleep(20);
+
+  printf("resume the av:\n");
+  proto_AVStart(handle);
+
+  sleep(200);
+
+  printf("stop the av");
+  proto_AVStop(handle, NORMAL);
+
+  sleep(3);
+  
+  ret = playback_get_key(data_set, parse_buf, sizeof(parse_buf));
+  if (ret > 0) {
+    printf("found the playback file: %s\n", parse_buf);
+  } else {
+    printf("the playback file is not existed!\n");
+  }
+
+  sleep(3000);
+  printf("now exit the process:\n");
+  proto_AVClose();
+
+  return 0;
+}
+
diff --git a/test/probe_test/Makefile b/test/probe_test/Makefile
index a9ba811..4b8a57b 100644
--- a/test/probe_test/Makefile
+++ b/test/probe_test/Makefile
@@ -19,16 +19,21 @@
 	@echo "  CC      " $@; 
 	@$(CC) $(CFLAGS) -c -o $@ $<
 
+FFMPEG_DIR = ../../thirdparty/ffmpeg
 OPENSSL_DIR = ../../thirdparty/openss
 
+LDFLAGS += -L$(FFMPEG_DIR)/lib
 LDFLAGS += -L$(OPENSSL_DIR)/lib
 LDFLAGS += -L../../
 LDLIBS += -lonvif_std
+LDLIBS += -lavcodec -lavdevice -lavfilter -lavformat \
+           -lavutil -lswresample -lswscale
 LDLIBS += -lcrypto -lssl -lpthread -ldl -lm -lrt
 
 INCLUDE += -I../../core/                               \
            -I../../comm/         \
            -I../../service      \
+           -I$(FFMPEG_DIR)/include          \
            -I$(OPENSSL_DIR)/include
 CFLAGS += $(INCLUDE)
 
diff --git a/test/ptz_test/Makefile b/test/ptz_test/Makefile
index 0eb8ec3..8328d26 100644
--- a/test/ptz_test/Makefile
+++ b/test/ptz_test/Makefile
@@ -21,16 +21,21 @@
 	@echo "  CC      " $@; 
 	@$(CC) $(CFLAGS) -c -o $@ $<
 
+FFMPEG_DIR = ../../thirdparty/ffmpeg
 OPENSSL_DIR = ../../thirdparty/openss
 
+LDFLAGS += -L$(FFMPEG_DIR)/lib
 LDFLAGS += -L$(OPENSSL_DIR)/lib
 LDFLAGS += -L../../
 LDLIBS += -lonvif_std
+LDLIBS += -lavcodec -lavdevice -lavfilter -lavformat \
+           -lavutil -lswresample -lswscale
 LDLIBS += -lcrypto -lssl -lpthread -ldl -lm -lrt
 
 INCLUDE += -I../../core/                               \
            -I../../comm/         \
            -I../../service        \
+           -I$(FFMPEG_DIR)/include          \
            -I$(OPENSSL_DIR)/include
 CFLAGS += $(INCLUDE)
 
diff --git a/test/ptz_test/ptz_test.c b/test/ptz_test/ptz_test.c
index 02d924d..bcc04f5 100644
--- a/test/ptz_test/ptz_test.c
+++ b/test/ptz_test/ptz_test.c
@@ -13,7 +13,6 @@
 {
     int ret;
     PosCur pos_get;
-    float data;
     int preset0, preset1, preset2;
     float pval, tval, zval;
     float speed_p, speed_t, speed_z;
@@ -131,6 +130,7 @@
     * secondly, zoom in the object that is describled with left-up and right-down pixel;
     * finally, restore the image as original size;
     */
+    float data;
     proto_PTZ_GetStatus(handle, &pos_get, USERNAME, PASSWORD);
     proto_PTZGetPT(handle, 0, 0, &pval, &tval, USERNAME, PASSWORD);
     proto_PTZSet(handle, pval, tval, pos_get.z, USERNAME, PASSWORD);

--
Gitblit v1.8.0