dvr: adjust file & add note [1/1]

PD#SWPL-18817

Problem:
New feature

Solution:
adjust file arch & add note

Verify:
Android Q + AC214

Change-Id: Ia3313ee6fc7a59f3ef18a020289cca6cacf437f2
Signed-off-by: Pengfei Liu <pengfei.liu@amlogic.com>
diff --git a/src/dvr_crypto.c b/src/dvr_crypto.c
index 9a35b9b..1d7dada 100644
--- a/src/dvr_crypto.c
+++ b/src/dvr_crypto.c
@@ -1,23 +1,25 @@
 #include <stdio.h>
 #include "dvr_crypto.h"
 
-int dvr_crypto_device_open(DVR_CryptoDeviceHandle *p_handle)
+int dvr_crypto_device_open(DVR_CryptoDeviceHandle_t *p_handle)
 {
   return 0;
 }
 
-int dvr_crypto_device_run(DVR_CryptoDeviceHandle handle,
-    uint8_t *buf_in, uint8_t *buf_out, DVR_CryptoParams *params)
+int dvr_crypto_device_run(DVR_CryptoDeviceHandle_t handle,
+    uint8_t *buf_in, uint8_t *buf_out, DVR_CryptoParams_t *params)
 {
   return 0;
 }
 
+#if 0
 int dvr_crypto_device_register(DVR_CryptoDeviceHandle handle, DVR_CryptoFunction cb, void *userdata, int is_enc)
 {
   return 0;
 }
+#endif
 
-int dvr_crypto_device_close(DVR_CryptoDeviceHandle handle)
+int dvr_crypto_device_close(DVR_CryptoDeviceHandle_t handle)
 {
   return 0;
 }
diff --git a/src/dvr_index_file.c b/src/dvr_index_file.c
deleted file mode 100644
index 258eda0..0000000
--- a/src/dvr_index_file.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <stdio.h>
-#include "dvr_index_file.h"
-
-int dvr_index_file_open(DVR_IndexFileHandle *p_handle, DVR_IndexFileOpenParams *p_params)
-{
-  return 0;
-}
-
-int dvr_index_file_close(DVR_IndexFileHandle handle)
-{
-  return 0;
-}
-
-int dvr_index_file_write(DVR_IndexFileHandle handle, uint64_t pcr, loff_t offset)
-{
-  return 0;
-}
-
-loff_t dvr_index_file_lookup_by_time(DVR_IndexFileHandle handle, time_t time)
-{
-  return 0;
-}
diff --git a/src/dvr_list_file.c b/src/dvr_list_file.c
deleted file mode 100644
index f3ed2ac..0000000
--- a/src/dvr_list_file.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-#include "dvr_list_file.h"
-
-
-int dvr_segment_list_file_store(const char *path, DVR_SegmentListInfo *p_info)
-{
-  return 0;
-}
-
-int dvr_segment_list_file_load(const char *path, DVR_SegmentListInfo *info)
-{
-  return 0;
-}
diff --git a/src/dvr_record.c b/src/dvr_record.c
new file mode 100644
index 0000000..89db271
--- /dev/null
+++ b/src/dvr_record.c
@@ -0,0 +1,241 @@
+#include <stdio.h>
+#include <pthread.h>
+#include "dvr_common.h"
+#include "dvr_record.h"
+#include "dvr_crypto.h"
+#include "record_device.h"
+#include "segment.h"
+#include "segment_file.h"
+
+#define MAX_DVR_RECORD_SESSION_COUNT 2
+typedef struct {
+  pthread_t                       thread;
+  Record_DeviceHandle_t           dev_handle;
+  Segment_Handle_t                segment_handle;
+  DVR_RecordState                 state;
+  char                            location[DVR_MAX_LOCATION_SIZE];
+  DVR_RecordSegmentStartParams_t  segment_params;
+} DVR_RecordContext_t;
+
+static DVR_RecordContext_t record_ctx[MAX_DVR_RECORD_SESSION_COUNT] = {
+  {
+    .state = DVR_RECORD_STATE_STOPPED
+  },
+  {
+    .state = DVR_RECORD_STATE_STOPPED
+  }
+};
+
+void *record_thread(void *arg)
+{
+  DVR_RecordContext_t *p_ctx = (DVR_RecordContext_t *)arg;
+  ssize_t len;
+  uint8_t *buf;
+  int block_size = 32*1024;
+  off_t pos = 0;
+  uint64_t pts = 0;
+  int ret;
+
+  buf = malloc(block_size);
+  if (!buf) {
+    DVR_DEBUG(1, "%s, malloc failed", __func__);
+    return NULL;
+  }
+
+  while (p_ctx->state == DVR_RECORD_STATE_STARTED) {
+    len = record_device_read(p_ctx->dev_handle, buf, sizeof(buf), 1000);
+#if 0
+    ret = sw_dmx_extract_pcr(buf, len, &pts, &pos);
+    if (ret == DVR_FAILURE) {
+      get_local_pts(&pts);
+    }
+#endif
+    pos += segment_tell(p_ctx->segment_handle);
+    ret = segment_update_pts(p_ctx->segment_handle, pts, pos);
+    ret = segment_write(p_ctx->segment_handle, buf, len);
+  }
+
+  free(buf);
+  return NULL;
+}
+
+int dvr_record_open(DVR_RecordHandle_t *p_handle, DVR_RecordOpenParams_t *params)
+{
+  DVR_RecordContext_t *p_ctx;
+  Record_DeviceOpenParams_t dev_open_params;
+  int ret;
+  int i;
+
+  DVR_ASSERT(p_handle);
+  DVR_ASSERT(params);
+
+  for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
+    if (record_ctx[i].state == DVR_RECORD_STATE_STOPPED) {
+      break;
+    }
+  }
+  DVR_ASSERT(record_ctx[i].state == DVR_RECORD_STATE_STOPPED);
+  p_ctx = &record_ctx[i];
+
+  /*Process params, todo*/
+  {
+  }
+
+  memset(&dev_open_params, 0, sizeof(dev_open_params));
+  /*Process dev_open_params, todo*/
+  {
+  }
+  ret = record_device_open(&p_ctx->dev_handle, &dev_open_params);
+  if (ret != DVR_SUCCESS) {
+    DVR_DEBUG(1, "%s, open record devices failed", __func__);
+    return DVR_FAILURE;
+  }
+
+  p_ctx->state = DVR_RECORD_STATE_OPENED;
+
+  *p_handle = i;
+  return DVR_SUCCESS;
+}
+
+int dvr_record_close(DVR_RecordHandle_t handle)
+{
+  DVR_RecordContext_t *p_ctx;
+  int ret;
+
+  DVR_ASSERT(handle < MAX_DVR_RECORD_SESSION_COUNT);
+  p_ctx = &record_ctx[handle];
+
+  DVR_ASSERT(p_ctx->state != DVR_RECORD_STATE_STOPPED);
+
+  ret = record_device_close(p_ctx->dev_handle);
+  if (ret != DVR_SUCCESS) {
+    DVR_DEBUG(1, "%s, failed", __func__);
+  }
+
+  p_ctx->state = DVR_RECORD_STATE_STOPPED;
+  return ret;
+}
+
+int dvr_record_register_encryption(DVR_RecordHandle_t handle,
+    DVR_CryptoFunction_t cb,
+    DVR_CryptoParams_t params,
+    void *userdata)
+{
+  return DVR_SUCCESS;
+}
+
+int dvr_record_start_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params)
+{
+  DVR_RecordContext_t *p_ctx;
+  Segment_OpenParams_t open_params;
+  int ret;
+  int i;
+
+  DVR_ASSERT(handle < MAX_DVR_RECORD_SESSION_COUNT);
+  p_ctx = &record_ctx[handle];
+
+  DVR_ASSERT(p_ctx->state != DVR_RECORD_STATE_STARTED);
+  DVR_ASSERT(params);
+
+  DVR_ASSERT(strlen(params->location) < DVR_MAX_LOCATION_SIZE);
+  memset(&open_params, 0, sizeof(open_params));
+  memcpy(open_params.location, params->location, strlen(params->location));
+  open_params.segment_id = params->segment.segment_id;
+  open_params.mode = SEGMENT_MODE_WRITE;
+
+  ret = segment_open(&open_params, &p_ctx->segment_handle);
+  DVR_ASSERT(ret == DVR_SUCCESS);
+
+  /*process params, todo*/
+  {
+    memcpy(p_ctx->location, params->location, strlen(params->location));
+    memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
+  }
+
+  for (i = 0; i < params->segment.nb_pids; i++) {
+    ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
+    DVR_ASSERT(ret);
+  }
+
+  ret = record_device_start(p_ctx->dev_handle);
+  DVR_ASSERT(ret);
+
+  pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
+  p_ctx->state = DVR_RECORD_STATE_STARTED;
+  return DVR_SUCCESS;
+}
+
+int dvr_record_next_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, DVR_RecordSegmentInfo_t *p_info)
+{
+  DVR_RecordContext_t *p_ctx;
+  int ret;
+  int i;
+
+  DVR_ASSERT(handle < MAX_DVR_RECORD_SESSION_COUNT);
+  p_ctx = &record_ctx[handle];
+
+  DVR_ASSERT(p_ctx->state != DVR_RECORD_STATE_STARTED);
+  DVR_ASSERT(params);
+  DVR_ASSERT(p_info);
+
+  /*Stop the on going record segment*/
+  ret = record_device_stop(p_ctx->dev_handle);
+  DVR_ASSERT(ret == DVR_SUCCESS);
+
+  p_ctx->state = DVR_RECORD_STATE_STOPPED;
+  pthread_join(p_ctx->thread, NULL);
+
+  ret = segment_file_store(p_ctx->location, p_ctx->segment_params.segment_id, p_info);
+  DVR_ASSERT(ret == DVR_SUCCESS);
+
+  /*Update segment info, todo*/
+  {
+  }
+
+  /*Start the new record segment*/
+  /*process params, todo*/
+  {
+    memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
+  }
+
+  for (i = 0; i < params->segment.nb_pids; i++) {
+    ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
+    DVR_ASSERT(ret);
+  }
+
+  ret = record_device_start(p_ctx->dev_handle);
+  DVR_ASSERT(ret);
+
+  pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
+  p_ctx->state = DVR_RECORD_STATE_STARTED;
+  return DVR_SUCCESS;
+}
+
+int dvr_record_stop_segment(DVR_RecordHandle_t handle, DVR_RecordSegmentInfo_t *p_info)
+{
+  DVR_RecordContext_t *p_ctx;
+  int ret;
+
+  DVR_ASSERT(handle < MAX_DVR_RECORD_SESSION_COUNT);
+  p_ctx = &record_ctx[handle];
+
+  DVR_ASSERT(p_ctx->state != DVR_RECORD_STATE_STOPPED);
+  DVR_ASSERT(p_info);
+
+  ret = record_device_stop(p_ctx->dev_handle);
+  DVR_ASSERT(ret == DVR_SUCCESS);
+
+  p_ctx->state = DVR_RECORD_STATE_STOPPED;
+  pthread_join(p_ctx->thread, NULL);
+
+  ret = segment_close(p_ctx->segment_handle);
+  DVR_ASSERT(ret == DVR_SUCCESS);
+
+  /*Update segment info, todo*/
+  {
+  }
+  ret = segment_file_store(p_ctx->location, p_ctx->segment_params.segment_id, p_info);
+  DVR_ASSERT(ret == DVR_SUCCESS);
+
+  return DVR_SUCCESS;
+}
diff --git a/src/dvr_segment.c b/src/dvr_segment.c
new file mode 100644
index 0000000..16135ce
--- /dev/null
+++ b/src/dvr_segment.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include "dvr_segment.h"
+
+int dvr_segment_delete(const char *location, uint64_t segment_id)
+{
+  return 0;
+}
+
+int dvr_segment_get_list(const char *location, uint32_t *p_segment_nb, uint64_t **pp_segment_ids)
+{
+  return 0;
+}
+
+int dvr_segment_get_info(const char *location, uint64_t segment_id, DVR_SegmentInfo *p_info)
+{
+  return 0;
+}
+
+int dvr_segment_link(const char *location, uint32_t nb_segments, uint64_t *p_segment_ids)
+{
+  return 0;
+}
diff --git a/src/dvr_segment_file.c b/src/dvr_segment_file.c
deleted file mode 100644
index 2dc44a2..0000000
--- a/src/dvr_segment_file.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <stdio.h>
-#include "dvr_segment_file.h"
-
-
-int dvr_segment_file_store(const char *location, uint64_t segment_id, DVR_SegmentStoreInfo *p_info)
-{
-  return 0;
-}
-
-int dvr_segment_file_load(const char *location, uint64_t segment_id, DVR_SegmentStoreInfo *p_info)
-{
-  return 0;
-}
-
-int dvr_segment_file_del(const char *location, uint64_t segment_id)
-{
-  return 0;
-}
-
diff --git a/src/index_file.c b/src/index_file.c
new file mode 100644
index 0000000..f08d75b
--- /dev/null
+++ b/src/index_file.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include "index_file.h"
+
+int index_file_open(Index_FileHandle_t *p_handle, Index_FileOpenParams_t *p_params)
+{
+  return 0;
+}
+
+int index_file_close(Index_FileHandle_t handle)
+{
+  return 0;
+}
+
+int index_file_write(Index_FileHandle_t handle, uint64_t pcr, loff_t offset)
+{
+  return 0;
+}
+
+loff_t index_file_lookup_by_time(Index_FileHandle_t handle, time_t time)
+{
+  return 0;
+}
diff --git a/src/list_file.c b/src/list_file.c
new file mode 100644
index 0000000..97dd42f
--- /dev/null
+++ b/src/list_file.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include "list_file.h"
+
+
+int segment_list_file_store(const char *path, Segment_ListInfo *p_info)
+{
+  return 0;
+}
+
+int segment_list_file_load(const char *path, Segment_ListInfo *info)
+{
+  return 0;
+}
diff --git a/src/record_device.c b/src/record_device.c
index 9759721..5187071 100644
--- a/src/record_device.c
+++ b/src/record_device.c
@@ -1,37 +1,37 @@
 #include <stdio.h>
 #include "record_device.h"
 
-int record_device_open(Record_DeviceHandle *p_handle, Record_DeviceOpenParams *params)
+int record_device_open(Record_DeviceHandle_t *p_handle, Record_DeviceOpenParams_t *params)
 {
   return 0;
 }
 
-int record_device_close(Record_DeviceHandle handle)
+int record_device_close(Record_DeviceHandle_t handle)
 {
   return 0;
 }
 
-int record_device_add_pid(Record_DeviceHandle handle, int pid)
+int record_device_add_pid(Record_DeviceHandle_t handle, int pid)
 {
   return 0;
 }
 
-int record_device_remove_pid(Record_DeviceHandle handle, int pid)
+int record_device_remove_pid(Record_DeviceHandle_t handle, int pid)
 {
   return 0;
 }
 
-int record_device_start(Record_DeviceHandle handle)
+int record_device_start(Record_DeviceHandle_t handle)
 {
   return 0;
 }
 
-int record_device_stop(Record_DeviceHandle handle)
+int record_device_stop(Record_DeviceHandle_t handle)
 {
   return 0;
 }
 
-ssize_t record_device_read(Record_DeviceHandle handle, void *buf, size_t len, int timeout)
+ssize_t record_device_read(Record_DeviceHandle_t handle, void *buf, size_t len, int timeout)
 {
   return 0;
 }
diff --git a/src/segment.c b/src/segment.c
new file mode 100644
index 0000000..a31c5dc
--- /dev/null
+++ b/src/segment.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include "dvr_common.h"
+#include "segment.h"
+
+#define MAX_SEGMENT_FD_COUNT (128)
+#define MAX_SEGMENT_PATH_SIZE (DVR_MAX_LOCATION_SIZE + 32)
+typedef struct {
+  //char location[DVR_MAX_LOCATION_SIZE];
+  //uint64_t segment_id;
+  FILE *ts_fp;                          /**< segment ts file fd*/
+  FILE *index_fp;                       /**< time index file fd*/
+} Segment_Context_t;
+
+typedef enum {
+  SEGMENT_FILE_TYPE_TS,
+  SEGMENT_FILE_TYPE_INDEX,
+} Segment_FileType_t;
+
+static void segment_get_fname(char fname[MAX_SEGMENT_PATH_SIZE],
+    char location[DVR_MAX_LOCATION_SIZE],
+    uint64_t segment_id,
+    Segment_FileType_t type)
+{
+  int offset;
+
+  memset(fname, 0, MAX_SEGMENT_PATH_SIZE);
+  strncpy(fname, location, strlen(location));
+  offset = strlen(location);
+  strncpy(fname + offset, "-", 1);
+  offset += 1;
+  sprintf(fname + offset, "%04llu", segment_id);
+  offset += 4;
+  if (type == SEGMENT_FILE_TYPE_TS)
+    strncpy(fname + offset, ".ts", 3);
+  else if (type == SEGMENT_FILE_TYPE_INDEX)
+    strncpy(fname + offset, ".idx", 4);
+}
+
+int segment_open(Segment_OpenParams_t *params, Segment_Handle_t *p_handle)
+{
+  Segment_Context_t *p_ctx;
+  char ts_fname[MAX_SEGMENT_PATH_SIZE];
+  char index_fname[MAX_SEGMENT_PATH_SIZE];
+
+  DVR_ASSERT(params);
+  DVR_ASSERT(p_handle);
+
+  DVR_DEBUG(1, "%s, location:%s, id:%d", __func__, params->location, params->segment_id);
+
+  p_ctx = malloc(sizeof(Segment_Context_t));
+  DVR_ASSERT(p_ctx);
+
+  memset(ts_fname, 0, sizeof(ts_fname));
+  segment_get_fname(ts_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_TS);
+
+  memset(index_fname, 0, sizeof(index_fname));
+  segment_get_fname(index_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_INDEX);
+
+  if (params->mode == SEGMENT_MODE_READ) {
+    p_ctx->ts_fp = fopen(ts_fname, "r");
+    p_ctx->index_fp = fopen(index_fname, "r");
+  } else if (params->mode == SEGMENT_MODE_WRITE) {
+    p_ctx->ts_fp = fopen(ts_fname, "w+");
+    p_ctx->index_fp = fopen(index_fname, "w+");
+  } else {
+    DVR_DEBUG(1, "%s, unknow mode use default", __func__);
+    p_ctx->ts_fp = fopen(ts_fname, "r");
+    p_ctx->index_fp = fopen(index_fname, "r");
+  }
+
+  if (!p_ctx->ts_fp || !p_ctx->index_fp) {
+    DVR_DEBUG(1, "%s open file failed [%p, %p], reason:%s", __func__,
+        p_ctx->ts_fp, p_ctx->index_fp, strerror(errno));
+    free(p_ctx);
+    p_handle = NULL;
+    return DVR_FAILURE;
+  }
+  p_handle = p_ctx;
+  return DVR_SUCCESS;
+}
+
+int segment_close(Segment_Handle_t handle)
+{
+  Segment_Context_t *p_ctx;
+
+  p_ctx = (Segment_Context_t *)handle;
+  DVR_ASSERT(p_ctx);
+
+  if (p_ctx->ts_fp) {
+    fclose(p_ctx->ts_fp);
+  }
+
+  if (p_ctx->index_fp) {
+    fclose(p_ctx->index_fp);
+  }
+
+  free(p_ctx);
+  return 0;
+}
+
+ssize_t segment_read(Segment_Handle_t handle, void *buf, size_t count)
+{
+  Segment_Context_t *p_ctx;
+
+  p_ctx = (Segment_Context_t *)handle;
+  DVR_ASSERT(p_ctx);
+  DVR_ASSERT(buf);
+  DVR_ASSERT(p_ctx->ts_fp);
+
+  return fread(p_ctx->ts_fp, 1, count, buf);
+}
+
+ssize_t segment_write(Segment_Handle_t handle, void *buf, size_t count)
+{
+  Segment_Context_t *p_ctx;
+
+  p_ctx = (Segment_Context_t *)handle;
+  DVR_ASSERT(p_ctx);
+  DVR_ASSERT(buf);
+  DVR_ASSERT(p_ctx->ts_fp);
+
+  return fwrite(p_ctx->ts_fp, 1, count, buf);
+}
+
+int segment_update_pts(Segment_Handle_t handle, uint64_t pts, off_t offset)
+{
+  Segment_Context_t *p_ctx;
+  char buf[256];
+
+  p_ctx = (Segment_Context_t *)handle;
+  DVR_ASSERT(p_ctx);
+  DVR_ASSERT(p_ctx->index_fp);
+
+  memset(buf, 0, sizeof(buf));
+  sprintf(buf, "{pts=%llu, offset=%llu}\n", pts, offset);
+
+  fputs(buf, p_ctx->index_fp);
+  return DVR_SUCCESS;
+}
+
+off_t segment_seek(Segment_Handle_t handle, uint64_t time)
+{
+  Segment_Context_t *p_ctx;
+  char buf[256];
+  char value[256];
+  uint64_t pts;
+  off_t offset;
+  char *p1, *p2;
+
+  p_ctx = (Segment_Context_t *)handle;
+  DVR_ASSERT(p_ctx);
+  DVR_ASSERT(p_ctx->index_fp);
+  DVR_ASSERT(p_ctx->ts_fp);
+
+	memset(buf, 0, sizeof(buf));
+  DVR_ASSERT(fseek(p_ctx->index_fp, 0, SEEK_SET) != -1);
+
+	while (fgets(buf, sizeof(buf), p_ctx->index_fp) != NULL) {
+    memset(value, 0, sizeof(value));
+    if ((p1 = strstr(buf, "pts="))) {
+      p1 += 4;
+      if ((p2 = strstr(buf, ","))) {
+        memcpy(value, p1, p2 - p1);
+      }
+      pts = strtoull(value, NULL, 10);
+    }
+
+    memset(value, 0, sizeof(value));
+    if ((p1 = strstr(buf, "offset="))) {
+      p1 += 7;
+      if ((p2 = strstr(buf, "}"))) {
+        memcpy(value, p1, p2 - p1);
+      }
+      offset = strtoull(value, NULL, 10);
+    }
+
+    memset(buf, 0, sizeof(buf));
+    DVR_DEBUG(1, "pts=%llu, offset=%ld\n", pts, offset);
+    if (time < pts) {
+      DVR_ASSERT(fseeko(p_ctx->ts_fp, offset, SEEK_SET) != -1);
+      return offset;
+    }
+	}
+
+  return DVR_FAILURE;
+}
+
+off_t segment_tell(Segment_Handle_t handle)
+{
+  Segment_Context_t *p_ctx;
+
+  p_ctx = (Segment_Context_t *)handle;
+  DVR_ASSERT(p_ctx);
+  DVR_ASSERT(p_ctx->ts_fp);
+
+  return ftello(p_ctx->ts_fp);
+}
diff --git a/src/segment_file.c b/src/segment_file.c
new file mode 100644
index 0000000..e834248
--- /dev/null
+++ b/src/segment_file.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include "segment_file.h"
+
+
+int segment_file_store(const char *location, uint64_t segment_id, Segment_StoreInfo_t *p_info)
+{
+  return 0;
+}
+
+int segment_file_load(const char *location, uint64_t segment_id, Segment_StoreInfo_t *p_info)
+{
+  return 0;
+}
+
+int segment_file_del(const char *location, uint64_t segment_id)
+{
+  return 0;
+}
+