Commit d5c982ed authored by John Stebbins's avatar John Stebbins

Merge branch 'master' of git.videolan.org:libbluray

parents b272bc0b 1cfc5386
......@@ -97,7 +97,7 @@ AC_TYPE_SIGNAL
# required headers
AC_CHECK_HEADERS([stdarg.h sys/types.h dirent.h errno.h libgen.h malloc.h])
AC_CHECK_HEADERS([stdlib.h mntent.h linux/cdrom.h inttypes.h])
AC_CHECK_HEADERS([stdlib.h mntent.h linux/cdrom.h inttypes.h strings.h])
AC_CHECK_HEADERS([sys/time.h time.h])
if test "${SYS}" != "mingw32" ; then
AC_CHECK_HEADERS(pthread.h,, [AC_MSG_ERROR([pthread.h required])])
......
......@@ -102,6 +102,7 @@ typedef struct {
xine_osd_t *osd;
bluray_input_class_t *class;
char *mrl;
char *disc_root;
char *disc_name;
......@@ -205,11 +206,16 @@ static void update_stream_info(bluray_input_plugin_t *this)
_x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER, bd_get_current_chapter(this->bdh) + 1);
}
static void update_title_info(bluray_input_plugin_t *this)
static void update_title_info(bluray_input_plugin_t *this, int playlist_id)
{
if (this->title_info)
bd_free_title_info(this->title_info);
this->title_info = bd_get_title_info(this->bdh, this->current_title_idx);
if (playlist_id < 0)
this->title_info = bd_get_title_info(this->bdh, this->current_title_idx);
else
this->title_info = bd_get_playlist_info(this->bdh, playlist_id);
if (!this->title_info) {
LOGMSG("bd_get_title_info(%d) failed\n", this->current_title_idx);
return;
......@@ -276,16 +282,16 @@ static void update_title_info(bluray_input_plugin_t *this)
update_stream_info(this);
}
static int open_title (bluray_input_plugin_t *this, int title)
static int open_title (bluray_input_plugin_t *this, int title_idx)
{
if (bd_select_title(this->bdh, title) <= 0) {
LOGMSG("bd_select_title(%d) failed\n", title);
if (bd_select_title(this->bdh, title_idx) <= 0) {
LOGMSG("bd_select_title(%d) failed\n", title_idx);
return 0;
}
this->current_title_idx = title;
this->current_title_idx = title_idx;
update_title_info(this);
update_title_info(this, -1);
return 1;
}
......@@ -338,6 +344,30 @@ static void wait_secs(bluray_input_plugin_t *this, unsigned seconds)
}
}
static void update_spu_channel(bluray_input_plugin_t *this, int channel)
{
if (this->stream->video_fifo) {
buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo);
buf->type = BUF_CONTROL_SPU_CHANNEL;
buf->decoder_info[0] = channel;
buf->decoder_info[1] = channel;
buf->decoder_info[2] = channel;
this->stream->video_fifo->put(this->stream->video_fifo, buf);
}
}
static void update_audio_channel(bluray_input_plugin_t *this, int channel)
{
if (this->stream->audio_fifo) {
buf_element_t *buf = this->stream->audio_fifo->buffer_pool_alloc(this->stream->audio_fifo);
buf->type = BUF_CONTROL_AUDIO_CHANNEL;
buf->decoder_info[0] = channel;
this->stream->audio_fifo->put(this->stream->audio_fifo, buf);
}
}
static void handle_libbluray_event(bluray_input_plugin_t *this, BD_EVENT ev)
{
switch (ev.event) {
......@@ -391,7 +421,7 @@ static void handle_libbluray_event(bluray_input_plugin_t *this, BD_EVENT ev)
lprintf("BD_EVENT_PLAYLIST %d\n", ev.param);
this->current_title_idx = bd_get_current_title(this->bdh);
this->current_clip = 0;
update_title_info(this);
update_title_info(this, ev.param);
stream_reset(this);
break;
......@@ -412,24 +442,20 @@ static void handle_libbluray_event(bluray_input_plugin_t *this, BD_EVENT ev)
case BD_EVENT_AUDIO_STREAM:
lprintf("BD_EVENT_AUDIO_STREAM %d\n", ev.param);
xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, ev.param - 1);
update_audio_channel(this, ev.param - 1);
break;
case BD_EVENT_PG_TEXTST:
lprintf("BD_EVENT_PG_TEXTST %s\n", ev.param ? "ON" : "OFF");
this->pg_enable = ev.param;
if (!this->pg_enable) {
_x_select_spu_channel(this->stream, -2);
} else {
_x_select_spu_channel(this->stream, this->pg_stream);
}
update_spu_channel(this, this->pg_enable ? this->pg_stream : -1);
break;
case BD_EVENT_PG_TEXTST_STREAM:
lprintf("BD_EVENT_PG_TEXTST_STREAM %d\n", ev.param);
this->pg_stream = ev.param - 1;
if (this->pg_enable) {
_x_select_spu_channel(this->stream, this->pg_stream);
update_spu_channel(this, this->pg_stream);
}
break;
......@@ -755,6 +781,8 @@ static off_t bluray_plugin_get_length (input_plugin_t *this_gen)
static uint32_t bluray_plugin_get_blocksize (input_plugin_t *this_gen)
{
(void)this_gen;
return ALIGNED_UNIT_SIZE;
}
......@@ -786,7 +814,7 @@ static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data
int channel = *((int *)data);
BLURAY_CLIP_INFO *clip = &this->title_info->clips[this->current_clip];
if (channel < clip->audio_stream_count) {
if (channel >= 0 && channel < clip->audio_stream_count) {
memcpy(data, clip->audio_streams[channel].lang, 4);
lprintf("INPUT_OPTIONAL_DATA_AUDIOLANG: %02d [pid 0x%04x]: %s\n",
channel, clip->audio_streams[channel].pid, clip->audio_streams[channel].lang);
......@@ -816,7 +844,7 @@ static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data
int channel = *((int *)data);
BLURAY_CLIP_INFO *clip = &this->title_info->clips[this->current_clip];
if (channel < clip->pg_stream_count) {
if (channel >= 0 && channel < clip->pg_stream_count) {
memcpy(data, clip->pg_streams[channel].lang, 4);
lprintf("INPUT_OPTIONAL_DATA_SPULANG: %02d [pid 0x%04x]: %s\n",
channel, clip->pg_streams[channel].pid, clip->pg_streams[channel].lang);
......@@ -1049,6 +1077,10 @@ static int bluray_plugin_open (input_plugin_t *this_gen)
bd_set_player_setting_str(this->bdh, BLURAY_PLAYER_SETTING_MENU_LANG, this->class->language);
bd_set_player_setting_str(this->bdh, BLURAY_PLAYER_SETTING_COUNTRY_CODE, this->class->country);
/* init eq */
BD_EVENT ev;
bd_get_event(this->bdh, &ev);
/* get disc name */
this->meta_dl = bd_get_meta(this->bdh);
......@@ -1134,6 +1166,8 @@ static input_plugin_t *bluray_class_get_instance (input_class_t *cls_gen, xine_s
this->event_queue = xine_event_new_queue (this->stream);
this->pg_stream = -1;
return &this->input_plugin;
}
......@@ -1196,6 +1230,8 @@ static const char *bluray_class_get_identifier (input_class_t *this_gen)
static char **bluray_class_get_autoplay_list (input_class_t *this_gen, int *num_files)
{
(void)this_gen;
static char *autoplay_list[] = { "bluray:/", NULL };
*num_files = 1;
......@@ -1224,6 +1260,8 @@ static void bluray_class_dispose (input_class_t *this_gen)
static void *bluray_init_plugin (xine_t *xine, void *data)
{
(void)data;
config_values_t *config = xine->config;
bluray_input_class_t *this = (bluray_input_class_t *) calloc(1, sizeof (bluray_input_class_t));
......
......@@ -89,7 +89,7 @@ libbluray_la_SOURCES=libbluray/bluray.h \
util/log_control.h \
util/bits.h \
util/logging.h
libbluray_la_HEADERS= libbluray/bluray.h file/filesystem.h util/log_control.h libbluray/keys.h libbluray/decoders/overlay.h libbluray/bdnav/meta_data.h
libbluray_la_HEADERS= libbluray/bluray.h file/filesystem.h util/log_control.h libbluray/keys.h libbluray/decoders/overlay.h libbluray/bdnav/meta_data.h libbluray/bdnav/clpi_data.h
libbluray_la_LDFLAGS= -version-info $(LIB_VERSION_INFO) $(DLOPEN_LDFLAGS) $(LIBXML2_LIBS)
if USING_BDJAVA
......
......@@ -14,7 +14,6 @@ noinst_PROGRAMS=bdsplice mpls_dump clpi_dump index_dump mobj_dump sound_dump \
libbluray_test bd_info list_titles hdmv_test
BLURAY_LIB = $(top_builddir)/src/libbluray.la
BLURAY_LIB_STATIC = $(top_builddir)/src/.libs/libbluray.a
if USING_BDJAVA
AM_CFLAGS += @BDJAVA_CFLAGS@
......@@ -26,29 +25,39 @@ bdsplice_SOURCES = \
bdsplice_LDADD = $(BLURAY_LIB)
mpls_dump_SOURCES = \
mpls_dump.c util.c util.h ../util/strutl.c
mpls_dump_LDADD = $(BLURAY_LIB_STATIC)
mpls_dump.c util.c util.h \
../util/strutl.c \
../util/logging.c \
../file/file_posix.c \
../file/dir_posix.c \
../libbluray/bdnav/mpls_parse.c \
../libbluray/bdnav/clpi_parse.c \
../libbluray/bdnav/navigation.c
clpi_dump_SOURCES = \
clpi_dump.c util.c util.h
clpi_dump_LDADD = $(BLURAY_LIB_STATIC)
clpi_dump.c util.c util.h \
../util/logging.c \
../file/file_posix.c \
../libbluray/bdnav/clpi_parse.c
sound_dump_SOURCES = \
sound_dump.c
sound_dump_LDADD = $(BLURAY_LIB_STATIC)
sound_dump.c \
../util/logging.c \
../file/file_posix.c \
../libbluray/bdnav/sound_parse.c
index_dump_SOURCES = \
index_dump.c
index_dump_LDADD = $(BLURAY_LIB_STATIC)
index_dump.c \
../util/logging.c \
../file/file_posix.c \
../libbluray/bdnav/index_parse.c
mobj_dump_SOURCES = \
mobj_dump.c
mobj_dump_LDADD = $(BLURAY_LIB_STATIC)
mobj_dump.c \
../util/logging.c \
../file/file_posix.c \
../libbluray/hdmv/mobj_parse.c \
../libbluray/hdmv/mobj_print.c
libbluray_test_SOURCES = \
libbluray_test.c ../util/logging.c
......
......@@ -36,23 +36,28 @@ void usage(void) {
printf("Usage: [path to disc] [starting object]\n");
}
int main(int argc, char** argv) {
printf("%s %s\n", argv[1], argv[2]);
int main(int argc, char** argv)
{
if (argc < 3) {
usage();
return 0;
}
printf("%s %s\n", argv[1], argv[2]);
BLURAY* bd = bd_open(argv[1], NULL);
bd_get_titles(bd, TITLES_ALL);
bd_select_title(bd, 1);
if (bd_start_bdj(bd, argv[2]))
if (!bd_start_bdj(bd, argv[2])) {
printf("Failed to start BD-J application.\n");
else {
} else {
while (1) { sleep(20); }
bd_stop_bdj(bd);
}
bd_close(bd);
return 0;
}
......@@ -21,6 +21,10 @@
#ifndef BD_FILESYSTEM_H_
#define BD_FILESYSTEM_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/*
......@@ -78,5 +82,8 @@ BD_FILE_OPEN bd_register_file(BD_FILE_OPEN p);
*/
BD_DIR_OPEN bd_register_dir(BD_DIR_OPEN p);
#ifdef __cplusplus
};
#endif
#endif /* BD_FILESYSTEM_H_ */
#include "util/logging.h"
#include "bdj_util.h"
jobject bdj_make_object(JNIEnv* env, const char* name, const char* sig, ...)
......@@ -5,6 +8,11 @@ jobject bdj_make_object(JNIEnv* env, const char* name, const char* sig, ...)
jclass obj_class = (*env)->FindClass(env, name);
jmethodID obj_constructor = (*env)->GetMethodID(env, obj_class, "<init>", sig);
if (!obj_class) {
BD_DEBUG(DBG_BDJ | DBG_CRIT, "Class %s not found\n", name);
return NULL;
}
va_list ap;
va_start(ap, sig);
jobject obj = (*env)->NewObjectV(env, obj_class, obj_constructor, ap);
......
......@@ -395,7 +395,9 @@ static jobject _parse_bdjo(JNIEnv* env, BITBUFFER* buf)
jobject bdjo_read(JNIEnv* env, const char* file)
{
jobject result = NULL;
BD_FILE_H *handle = file_open(file, "rb");
if (handle == NULL) {
BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to open bdjo file (%s)\n", file);
return NULL;
......@@ -404,26 +406,31 @@ jobject bdjo_read(JNIEnv* env, const char* file)
file_seek(handle, 0, SEEK_END);
int64_t length = file_tell(handle);
if (length > 0) {
if (length <= 0) {
BD_DEBUG(DBG_BDJ | DBG_CRIT, "Error reading %s\n", file);
} else {
file_seek(handle, 0, SEEK_SET);
uint8_t *data = malloc(length);
int64_t size_read = file_read(handle, data, length);
if (size_read < length) {
free(data);
return NULL;
}
BD_DEBUG(DBG_BDJ | DBG_CRIT, "Error reading %s\n", file);
BITBUFFER* buf = malloc(sizeof(BITBUFFER));
bb_init(buf, data, length);
} else {
BITBUFFER *buf = malloc(sizeof(BITBUFFER));
bb_init(buf, data, length);
jobject result = _parse_bdjo(env, buf);
result = _parse_bdjo(env, buf);
free(buf);
file_close(handle);
free(buf);
}
return result;
} else {
return NULL;
free(data);
}
file_close(handle);
return result;
}
/*
* This file is part of libbluray
* Copyright (C) 2009-2010 John Stebbins
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#if !defined(_CLPI_DATA_H_)
#define _CLPI_DATA_H_
#include <stdint.h>
typedef struct
{
uint16_t pcr_pid;
uint32_t spn_stc_start;
uint32_t presentation_start_time;
uint32_t presentation_end_time;
} CLPI_STC_SEQ;
typedef struct
{
uint32_t spn_atc_start;
uint8_t num_stc_seq;
uint8_t offset_stc_id;
CLPI_STC_SEQ *stc_seq;
} CLPI_ATC_SEQ;
typedef struct
{
uint8_t num_atc_seq;
CLPI_ATC_SEQ *atc_seq;
} CLPI_SEQ_INFO;
typedef struct
{
uint8_t validity;
uint8_t format_id[5];
} CLPI_TS_TYPE;
typedef struct
{
uint32_t delta;
uint8_t file_id[6];
uint8_t file_code[5];
} CLPI_ATC_DELTA;
typedef struct
{
uint8_t clip_stream_type;
uint8_t application_type;
uint8_t is_atc_delta;
uint32_t ts_recording_rate;
uint32_t num_source_packets;
CLPI_TS_TYPE ts_type_info;
uint8_t atc_delta_count;
CLPI_ATC_DELTA *atc_delta;
} CLPI_CLIP_INFO;
typedef struct
{
uint16_t pid;
uint8_t coding_type;
uint8_t format;
uint8_t rate;
uint8_t aspect;
uint8_t oc_flag;
uint8_t char_code;
uint8_t lang[4];
} CLPI_PROG_STREAM;
typedef struct
{
uint32_t spn_program_sequence_start;
uint16_t program_map_pid;
uint8_t num_streams;
uint8_t num_groups;
CLPI_PROG_STREAM *streams;
} CLPI_PROG;
typedef struct
{
uint8_t num_prog;
CLPI_PROG *progs;
} CLPI_PROG_INFO;
typedef struct
{
int ref_ep_fine_id;
int pts_ep;
uint32_t spn_ep;
} CLPI_EP_COARSE;
typedef struct
{
uint8_t is_angle_change_point;
uint8_t i_end_position_offset;
int pts_ep;
int spn_ep;
} CLPI_EP_FINE;
typedef struct
{
uint16_t pid;
uint8_t ep_stream_type;
int num_ep_coarse;
int num_ep_fine;
uint32_t ep_map_stream_start_addr;
CLPI_EP_COARSE *coarse;
CLPI_EP_FINE *fine;
} CLPI_EP_MAP_ENTRY;
typedef struct
{
uint8_t type;
// ep_map
uint8_t num_stream_pid;
CLPI_EP_MAP_ENTRY *entry;
} CLPI_CPI;
typedef struct clpi_cl {
uint32_t type_indicator;
uint32_t type_indicator2;
uint32_t sequence_info_start_addr;
uint32_t program_info_start_addr;
uint32_t cpi_start_addr;
uint32_t clip_mark_start_addr;
uint32_t ext_data_start_addr;
CLPI_CLIP_INFO clip;
CLPI_SEQ_INFO sequence;
CLPI_PROG_INFO program;
CLPI_CPI cpi;
// skip clip mark & extension data
} CLPI_CL;
#endif // _CLPI_DATA_H_
......@@ -23,6 +23,7 @@
#include "clpi_parse.h"
#include <stdlib.h>
#include <string.h>
#define CLPI_SIG1 ('H' << 24 | 'D' << 16 | 'M' << 8 | 'V')
#define CLPI_SIG2A ('0' << 24 | '2' << 16 | '0' << 8 | '0')
......@@ -625,3 +626,85 @@ clpi_parse(char *path, int verbose)
return cl;
}
CLPI_CL*
clpi_copy(CLPI_CL* dest_cl, CLPI_CL* src_cl)
{
int ii, jj;
if (dest_cl && src_cl) {
dest_cl->clip.clip_stream_type = src_cl->clip.clip_stream_type;
dest_cl->clip.application_type = src_cl->clip.application_type;
dest_cl->clip.is_atc_delta = src_cl->clip.is_atc_delta;
dest_cl->clip.atc_delta_count = src_cl->clip.atc_delta_count;
dest_cl->clip.ts_recording_rate = src_cl->clip.ts_recording_rate;
dest_cl->clip.num_source_packets = src_cl->clip.num_source_packets;
dest_cl->clip.ts_type_info.validity = src_cl->clip.ts_type_info.validity;
memcpy(dest_cl->clip.ts_type_info.format_id, src_cl->clip.ts_type_info.format_id, 5);
dest_cl->clip.atc_delta = malloc(src_cl->clip.atc_delta_count * sizeof(CLPI_ATC_DELTA));
for (ii = 0; ii < src_cl->clip.atc_delta_count; ii++) {
dest_cl->clip.atc_delta[ii].delta = src_cl->clip.atc_delta[ii].delta;
memcpy(dest_cl->clip.atc_delta[ii].file_id, src_cl->clip.atc_delta[ii].file_id, 6);
memcpy(dest_cl->clip.atc_delta[ii].file_code, src_cl->clip.atc_delta[ii].file_code, 5);
}
dest_cl->sequence.num_atc_seq = src_cl->sequence.num_atc_seq;
dest_cl->sequence.atc_seq = malloc(src_cl->sequence.num_atc_seq * sizeof(CLPI_ATC_SEQ));
for (ii = 0; ii < src_cl->sequence.num_atc_seq; ii++) {
dest_cl->sequence.atc_seq[ii].spn_atc_start = src_cl->sequence.atc_seq[ii].spn_atc_start;
dest_cl->sequence.atc_seq[ii].offset_stc_id = src_cl->sequence.atc_seq[ii].offset_stc_id;
dest_cl->sequence.atc_seq[ii].num_stc_seq = src_cl->sequence.atc_seq[ii].num_stc_seq;
dest_cl->sequence.atc_seq[ii].stc_seq = malloc(src_cl->sequence.atc_seq[ii].num_stc_seq * sizeof(CLPI_STC_SEQ));
for (jj = 0; jj < src_cl->sequence.atc_seq[ii].num_stc_seq; jj++) {
dest_cl->sequence.atc_seq[ii].stc_seq[jj].spn_stc_start = src_cl->sequence.atc_seq[ii].stc_seq[jj].spn_stc_start;
dest_cl->sequence.atc_seq[ii].stc_seq[jj].pcr_pid = src_cl->sequence.atc_seq[ii].stc_seq[jj].pcr_pid;
dest_cl->sequence.atc_seq[ii].stc_seq[jj].presentation_start_time = src_cl->sequence.atc_seq[ii].stc_seq[jj].presentation_start_time;
dest_cl->sequence.atc_seq[ii].stc_seq[jj].presentation_end_time = src_cl->sequence.atc_seq[ii].stc_seq[jj].presentation_end_time;
}
}
dest_cl->program.num_prog = src_cl->program.num_prog;
dest_cl->program.progs = malloc(src_cl->program.num_prog * sizeof(CLPI_PROG));
for (ii = 0; ii < src_cl->program.num_prog; ii++) {
dest_cl->program.progs[ii].spn_program_sequence_start = src_cl->program.progs[ii].spn_program_sequence_start;
dest_cl->program.progs[ii].program_map_pid = src_cl->program.progs[ii].program_map_pid;
dest_cl->program.progs[ii].num_streams = src_cl->program.progs[ii].num_streams;
dest_cl->program.progs[ii].num_groups = src_cl->program.progs[ii].num_groups;
dest_cl->program.progs[ii].streams = malloc(src_cl->program.progs[ii].num_streams * sizeof(CLPI_PROG_STREAM));
for (jj = 0; jj < src_cl->program.progs[ii].num_streams; jj++) {
dest_cl->program.progs[ii].streams[jj].coding_type = src_cl->program.progs[ii].streams[jj].coding_type;
dest_cl->program.progs[ii].streams[jj].pid = src_cl->program.progs[ii].streams[jj].pid;
dest_cl->program.progs[ii].streams[jj].format = src_cl->program.progs[ii].streams[jj].format;
dest_cl->program.progs[ii].streams[jj].rate = src_cl->program.progs[ii].streams[jj].rate;
dest_cl->program.progs[ii].streams[jj].aspect = src_cl->program.progs[ii].streams[jj].aspect;
dest_cl->program.progs[ii].streams[jj].oc_flag = src_cl->program.progs[ii].streams[jj].oc_flag;
dest_cl->program.progs[ii].streams[jj].char_code = src_cl->program.progs[ii].streams[jj].char_code;
memcpy(dest_cl->program.progs[ii].streams[jj].lang,src_cl->program.progs[ii].streams[jj].lang,4);
}
}
dest_cl->cpi.num_stream_pid = src_cl->cpi.num_stream_pid;
dest_cl->cpi.entry = malloc(src_cl->cpi.num_stream_pid * sizeof(CLPI_EP_MAP_ENTRY));
for (ii = 0; ii < dest_cl->cpi.num_stream_pid; ii++) {
dest_cl->cpi.entry[ii].pid = src_cl->cpi.entry[ii].pid;
dest_cl->cpi.entry[ii].ep_stream_type = src_cl->cpi.entry[ii].ep_stream_type;
dest_cl->cpi.entry[ii].num_ep_coarse = src_cl->cpi.entry[ii].num_ep_coarse;
dest_cl->cpi.entry[ii].num_ep_fine = src_cl->cpi.entry[ii].num_ep_fine;
dest_cl->cpi.entry[ii].ep_map_stream_start_addr = src_cl->cpi.entry[ii].ep_map_stream_start_addr;
dest_cl->cpi.entry[ii].coarse = malloc(src_cl->cpi.entry[ii].num_ep_coarse * sizeof(CLPI_EP_COARSE));
for (jj = 0; jj < src_cl->cpi.entry[ii].num_ep_coarse; jj++) {
dest_cl->cpi.entry[ii].coarse[jj].ref_ep_fine_id = src_cl->cpi.entry[ii].coarse[jj].ref_ep_fine_id;
dest_cl->cpi.entry[ii].coarse[jj].pts_ep = src_cl->cpi.entry[ii].coarse[jj].pts_ep;
dest_cl->cpi.entry[ii].coarse[jj].spn_ep = src_cl->cpi.entry[ii].coarse[jj].spn_ep;
}
dest_cl->cpi.entry[ii].fine = malloc(src_cl->cpi.entry[ii].num_ep_fine * sizeof(CLPI_EP_FINE));
for (jj = 0; jj < src_cl->cpi.entry[ii].num_ep_fine; jj++) {
dest_cl->cpi.entry[ii].fine[jj].is_angle_change_point = src_cl->cpi.entry[ii].fine[jj].is_angle_change_point;
dest_cl->cpi.entry[ii].fine[jj].i_end_position_offset = src_cl->cpi.entry[ii].fine[jj].i_end_position_offset;
dest_cl->cpi.entry[ii].fine[jj].pts_ep = src_cl->cpi.entry[ii].fine[jj].pts_ep;
dest_cl->cpi.entry[ii].fine[jj].spn_ep = src_cl->cpi.entry[ii].fine[jj].spn_ep;
}
}