libdvbpsi 소스 코드 분석 (2) main 함수
분석 편 의 를 위해 매크로 HAVESYS_SOCKET_H 격 리 된 socket 코드 를 제거 하고 libdvbpsi 자체 의 실현 에 만 관심 을 가 집 니 다.
1. 데이터 구조의 디자인:
1.1 포획 기 capture 의 데이터 구 조 는 다음 과 같다.
typedef struct dvbinfo_capture_s
{
fifo_t *fifo;
fifo_t *empty;
pthread_mutex_t lock;
pthread_cond_t fifo_full;
bool b_fifo_full;
size_t size; /* prefered capture size */
params_t *params;
bool b_alive;
} dvbinfo_capture_t;
데이터 구조 에서 알 수 있 듯 이 demo 는 현지의 autotest 이기 때문에 유명한 파이프 fifo 로 테스트 한다.명령 행 터미널 에서 ts 스 트림 파일 을 읽 고 한 스 레 드 는 buffer 의 데이터 push 를 fifo 에 계속 들 어 갑 니 다. 또한 메 인 스 레 드 는 fifo pop 에서 데 이 터 를 계속 내 보 내 고 해석 합 니 다. fifo 에서 읽 은 데 이 터 는 0 1.2, dvbinfo 입 니 다.capture_t 중의 paramst 구조 체 typedef struct params_s
{
/* parameters */
char *output;
char *input;
int port;
char *mcast_interface;
bool b_udp;
bool b_tcp;
bool b_file;
/* */
int fd_in;
int fd_out;
int debug;
bool b_verbose;
bool b_monitor; /* run in daemon mode */
/* statistics */
bool b_summary; /* write summary */
struct summary_s {
int mode; /* one of: i_summary_mode */
int64_t period; /* summary period in ms */
char *file; /* summary file name */
FILE *fd; /* summary file descriptor */
} summary;
/* read data from file of socket */
ssize_t (*pf_read)(int fd, void *buf, size_t count);
ssize_t (*pf_write)(int fd, const void *buf, size_t count);
} params_t;
2. main 함수 입구 int main(int argc, char **pp_argv)
{
dvbinfo_capture_t capture;
params_t *param = NULL;
char c;
if (argc == 1)
usage();
param = params_init();
capture.params = param;
capture.fifo = fifo_new();
capture.empty = fifo_new();
capture.b_fifo_full = false;
pthread_mutex_init(&capture.lock, NULL); //
pthread_cond_init(&capture.fifo_full, NULL); //
static const struct option long_options[] =
{
{ "debug", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
/* - inputs - */
{ "file", required_argument, NULL, 'f' },
{ NULL, 0, NULL, 0 }
};
/*
*/
while ((c = getopt_long(argc, pp_argv, "d:f:h", long_options, NULL)) != -1)
{
switch(c)
{
case 'd':
if (optarg)
{
param->debug = 0;
if (strncmp(optarg, "error", 5) == 0)
param->debug = 1;
else if (strncmp(optarg, "warn", 4) == 0)
param->debug = 2;
else if (strncmp(optarg, "debug", 5) == 0)
param->debug = 3;
}
break;
case 'f':
if (optarg)
{
/* ts , asprintf */
if (asprintf(¶m->input, "%s", optarg) < 0)
{
fprintf(stderr, "error: out of memory
");
params_free(param);
usage();
}
/* */
param->pf_read = read;
param->b_file = true;
}
break;
case ':':
fprintf(stderr, "Option %c is missing arguments
", c);
params_free(param);
exit(EXIT_FAILURE);
break;
case '?':
fprintf(stderr, "Unknown option %c found
", c);
params_free(param);
exit(EXIT_FAILURE);
break;
case 'h':
default:
params_free(param);
usage();
break;
}
};
if (param->input == NULL)
{
libdvbpsi_log(param, DVBINFO_LOG_ERROR, "No source given
");
params_free(param);
usage(); /* exits application */
}
{
capture.size = 188; //ts packet 188
libdvbpsi_log(param, DVBINFO_LOG_INFO, "Examining: %s
",
param->input);
}
/* Capture thread */
dvbinfo_open(param); // ts ,
pthread_t handle; // pid
capture.b_alive = true;
/* capture */
if (pthread_create(&handle, NULL, dvbinfo_capture, (void *)&capture) < 0)
{
libdvbpsi_log(param, DVBINFO_LOG_ERROR, "failed creating thread
");
dvbinfo_close(param);
params_free(param);
exit(EXIT_FAILURE);
}
/* fifo , PSI */
int err = dvbinfo_process(&capture);
/* fifo 0, ts 。 cpature alive false, */
capture.b_alive = false; /* stop thread */
if (pthread_join(handle, NULL) < 0)
libdvbpsi_log(param, DVBINFO_LOG_ERROR, "error joining capture thread
");
dvbinfo_close(param);
/* cleanup */
fifo_wake((&capture)->fifo);
fifo_wake((&capture)->empty);
fifo_free((&capture)->fifo);
fifo_free((&capture)->empty);
pthread_mutex_destroy(&capture.lock);
pthread_cond_destroy(&capture.fifo_full);
params_free(param);
if (err < 0)
exit(EXIT_FAILURE);
else
exit(EXIT_SUCCESS);
}
3. 스 레 드 인 스 턴 스 (루틴) dvbinfocapture 의 분석 [주해] 스 레 드 dvbinfocapture 는 ts 스 트림 파일 push 를 fifo 에 계속 넣 는 동시에 dvbinfoprocess 는 fifo 에서 데 이 터 를 계속 꺼 내 고 모든 specific decoder 에 section 분석 을 제공 하여 table 표 의 재 구축 을 완성 합 니 다.스 레 드 dvbinfo 까지capture 는 ts 스 트림 파일 을 읽 었 고 dvbinfoprocess 처리 가 완료 되 어야 capture 의 활동 표지 위 capture. balive 는 false 로 설정 하고 마지막 으로 스 레 드 를 종료 하 며 스 레 드 자원 을 방출 합 니 다.전형 적 인 '생산자 - 소비자' 모델.static void *dvbinfo_capture(void *data)
{
dvbinfo_capture_t *capture = (dvbinfo_capture_t *)data;
const params_t *param = capture->params;
bool b_eof = false;
while (capture->b_alive && !b_eof)
{
buffer_t *buffer;
if (fifo_count(capture->empty) == 0)
buffer = buffer_new(capture->size);
else
buffer = fifo_pop(capture->empty);
if (buffer == NULL) /* out of memory */
break;
ssize_t size = param->pf_read(param->fd_in, buffer->p_data, buffer->i_size);
if (size < 0) /* short read ? */
{
fifo_push(capture->empty, buffer);
continue;
}
else if (size == 0)
{
fifo_push(capture->empty, buffer);
b_eof = true;
continue;
}
buffer->i_date = mdate();
/* check fifo size */
if (fifo_size(capture->fifo) >= FIFO_THRESHOLD_SIZE)
{
pthread_mutex_lock(&capture->lock);
capture->b_fifo_full = true;
pthread_mutex_unlock(&capture->lock);
if (param->b_file)
{
/* wait till buffer becomes smaller again */
pthread_mutex_lock(&capture->lock);
while(capture->b_fifo_full)
pthread_cond_wait(&capture->fifo_full, &capture->lock);
pthread_mutex_unlock(&capture->lock);
}
else
{
libdvbpsi_log(capture->params, DVBINFO_LOG_ERROR,
"error fifo full discarding buffer");
fifo_push(capture->empty, buffer);
continue;
}
}
/* store buffer */
fifo_push(capture->fifo, buffer);
buffer = NULL;
}
capture->b_alive = false;
fifo_wake(capture->fifo);
return NULL;
}
4、dvbinfo_process 는 ts 흐름 에서 각종 table 의 해석 을 책임 집 니 다 static int dvbinfo_process(dvbinfo_capture_t *capture)
{
int err = -1;
bool b_error = false;
params_t *param = capture->params;
buffer_t *buffer = NULL;
char *psz_temp = NULL;
mtime_t deadline = 0;
if (param->b_summary)
{
if (asprintf(&psz_temp, "%s.part", param->summary.file) < 0)
{
libdvbpsi_log(param, DVBINFO_LOG_ERROR, "Could not create temporary summary file %s
",
param->summary.file);
return err;
}
deadline = mdate() + param->summary.period;
}
/*MPEG-TS PSI decoders create*/
ts_stream_t *stream = libdvbpsi_init(param->debug, &libdvbpsi_log, (void *)param);
if (!stream)
goto out;
while (!b_error)
{
/* Wait till fifo has emptied */
if (!capture->b_alive && (fifo_count(capture->fifo) == 0))
break;
/* Wait for data to arrive */
buffer = fifo_pop(capture->fifo);
if (buffer == NULL)
continue;
if (param->output)
{
size_t size = param->pf_write(param->fd_out, buffer->p_data, buffer->i_size);
if (size < 0) /* error writing */
{
libdvbpsi_log(param, DVBINFO_LOG_ERROR,
"error (%d) writting to %s", errno, param->output);
break;
}
else if (size < buffer->i_size) /* short writting disk full? */
{
libdvbpsi_log(param, DVBINFO_LOG_ERROR,
"error writting to %s (disk full?)", param->output);
break;
}
}
if (!libdvbpsi_process(stream, buffer->p_data, buffer->i_size, buffer->i_date))
b_error = true;
/* summary statistics */
if (param->b_summary)
{
if (mdate() >= deadline)
{
FILE *fd = fopen(psz_temp, "w+");
if (fd)
{
libdvbpsi_summary(fd, stream, param->summary.mode);
fflush(fd);
fclose(fd);
unlink(param->summary.file);
rename(psz_temp, param->summary.file);
}
else
{
libdvbpsi_log(param, DVBINFO_LOG_ERROR,
"failed opening summary file (disabling summary logging)
");
param->b_summary = false;
}
deadline = mdate() + param->summary.period;
}
}
/* reuse buffer */
fifo_push(capture->empty, buffer);
buffer = NULL;
/* check fifo size */
if (fifo_size(capture->fifo) < FIFO_THRESHOLD_SIZE)
{
pthread_mutex_lock(&capture->lock);
capture->b_fifo_full = false;
pthread_cond_signal(&capture->fifo_full);
pthread_mutex_unlock(&capture->lock);
}
}
assert(fifo_count(capture->fifo) == 0);
libdvbpsi_exit(stream);
err = 0;
out:
if (b_error)
libdvbpsi_log(param, DVBINFO_LOG_ERROR, "error while processing
" );
if (buffer) buffer_free(buffer);
free(psz_temp);
return err;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C++ 정리 - 10 main 함수모든 C++ 프로그램엔 main함수가 있어야 한다. (Dynamic-link libraries와 static libraries 에는 main함수가 없다) 내 프로그램에서 main함수를 호출할 수 없다. main함수를...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.