00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "NvUtils.h"
00030 #include <errno.h>
00031 #include <fstream>
00032 #include <iostream>
00033 #include <cstdlib>
00034 #include <cstring>
00035 #include <linux/videodev2.h>
00036 #include <pthread.h>
00037 #include <string.h>
00038 #include <unistd.h>
00039 #include "NvCudaProc.h"
00040 #include "nvbuf_utils.h"
00041 #include "v4l2_nv_extensions.h"
00042 #include "v4l2_backend_test.h"
00043 #include <sys/time.h>
00044
00045 #ifdef ENABLE_GIE
00046 #include "gie_inference.h"
00047 #endif
00048
00049 #define TEST_ERROR(cond, str, label) if(cond) { \
00050 cerr << str << endl; \
00051 error = 1; \
00052 goto label; }
00053
00054 #define CHUNK_SIZE 4000000
00055 #ifndef MIN
00056 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
00057 #endif
00058
00059 #define NAL_UNIT_START_CODE 0x00000001
00060 #define MIN_CHUNK_SIZE 50
00061 #define USE_CPU_FOR_INTFLOAT_CONVERSION 0
00062
00063 static const int IMAGE_WIDTH = 1920;
00064 static const int IMAGE_HEIGHT = 1080;
00065 const char *GOOGLE_NET_DEPLOY_NAME =
00066 "../../data/model/GoogleNet-modified.prototxt";
00067 const char *GOOGLE_NET_MODEL_NAME =
00068 "../../data/model/GoogleNet-modified-online_iter_30000.caffemodel";
00069
00070 #define IS_NAL_UNIT_START(buffer_ptr) (!buffer_ptr[0] && !buffer_ptr[1] && \
00071 !buffer_ptr[2] && (buffer_ptr[3] == 1))
00072
00073 #define IS_NAL_UNIT_START1(buffer_ptr) (!buffer_ptr[0] && !buffer_ptr[1] && \
00074 (buffer_ptr[2] == 1))
00075
00076 using namespace std;
00077
00078 #ifdef ENABLE_GIE
00079 #define OSD_BUF_NUM 100
00080 static int frame_num = 1;
00081
00082
00083
00084 queue<Shared_Buffer> GIE_Buffer_Queue;
00085 pthread_mutex_t GIE_lock;
00086 pthread_cond_t GIE_cond;
00087 int GIE_Stop = 0;
00088 pthread_t GIE_Thread_handle;
00089
00090 using namespace nvinfer1;
00091 using namespace nvcaffeparser1;
00092
00093 GIE_Context g_gie_context;
00094 void *gie_thread(void *data);
00095
00096 #endif
00097
00098 EGLDisplay egl_display;
00099 jpeg_enc_context_t g_jpeg_enc_context;
00100
00101 static uint64_t ts[CHANNEL_NUM];
00102 static uint64_t time_scale[CHANNEL_NUM];
00103
00104 static int
00105 init_jpeg_context()
00106 {
00107 pthread_mutex_init(&g_jpeg_enc_context.queue_lock, NULL);
00108 g_jpeg_enc_context.JpegEnc = NvJPEGEncoder::createJPEGEncoder("jpeg_enc");
00109
00110 if (g_jpeg_enc_context.JpegEnc == NULL)
00111 {
00112 cout<<"create jpeg encode failed"<<endl;
00113 return 0;
00114 }
00115
00116 g_jpeg_enc_context.pbuf = new unsigned char[JPEG_ENC_BUF_SIZE];
00117 g_jpeg_enc_context.buf_size = JPEG_ENC_BUF_SIZE;
00118 memset(g_jpeg_enc_context.filename, 0,
00119 sizeof(g_jpeg_enc_context.filename));
00120
00121 return 1;
00122 }
00123
00124 static int
00125 destroy_jpeg_context()
00126 {
00127 delete []g_jpeg_enc_context.pbuf;
00128 if (g_jpeg_enc_context.JpegEnc)
00129 delete g_jpeg_enc_context.JpegEnc;
00130
00131 return 1;
00132 }
00133
00134 static int
00135 read_decoder_input_nalu(ifstream * stream, NvBuffer * buffer,
00136 char *parse_buffer, streamsize parse_buffer_size)
00137 {
00138
00139 char *buffer_ptr = (char *) buffer->planes[0].data;
00140
00141 char *stream_ptr;
00142 bool nalu_found = false;
00143
00144 streamsize bytes_read;
00145 streamsize stream_initial_pos = stream->tellg();
00146
00147 stream->read(parse_buffer, parse_buffer_size);
00148 bytes_read = stream->gcount();
00149
00150 if (bytes_read == 0)
00151 {
00152 return buffer->planes[0].bytesused = 0;
00153 }
00154
00155
00156 stream_ptr = parse_buffer;
00157 while ((stream_ptr - parse_buffer) < (bytes_read - 3))
00158 {
00159 nalu_found = IS_NAL_UNIT_START(stream_ptr) ||
00160 IS_NAL_UNIT_START1(stream_ptr);
00161 if (nalu_found)
00162 {
00163 break;
00164 }
00165 stream_ptr++;
00166 }
00167
00168
00169 if (!nalu_found)
00170 {
00171 cerr << "Could not read nal unit from file. File seems to be corrupted"
00172 << endl;
00173 return -1;
00174 }
00175
00176 memcpy(buffer_ptr, stream_ptr, 4);
00177 buffer_ptr += 4;
00178 buffer->planes[0].bytesused = 4;
00179 stream_ptr += 4;
00180
00181
00182 while ((stream_ptr - parse_buffer) < (bytes_read - 3))
00183 {
00184 if (IS_NAL_UNIT_START(stream_ptr) || IS_NAL_UNIT_START1(stream_ptr))
00185 {
00186 streamsize seekto = stream_initial_pos +
00187 (stream_ptr - parse_buffer);
00188 if (stream->eof())
00189 {
00190 stream->clear();
00191 }
00192 stream->seekg(seekto, stream->beg);
00193 return 0;
00194 }
00195 *buffer_ptr = *stream_ptr;
00196 buffer_ptr++;
00197 stream_ptr++;
00198 buffer->planes[0].bytesused++;
00199 }
00200
00201
00202 cerr << "Could not read nal unit from file. File seems to be corrupted"
00203 << endl;
00204 return -1;
00205 }
00206
00207 static int
00208 read_decoder_input_chunk(ifstream * stream, NvBuffer * buffer)
00209 {
00210
00211 streamsize bytes_to_read = MIN(CHUNK_SIZE, buffer->planes[0].length);
00212
00213 stream->read((char *) buffer->planes[0].data, bytes_to_read);
00214
00215
00216 buffer->planes[0].bytesused = stream->gcount();
00217 return 0;
00218 }
00219
00220
00221 static int
00222 init_decode_ts()
00223 {
00224 for (uint32_t i = 0; i < CHANNEL_NUM; i++)
00225 {
00226 ts[i] = 0L;
00227 time_scale[i] = 33000 * 10;
00228 }
00229
00230 return 1;
00231 }
00232
00233 static int
00234 assign_decode_ts(struct v4l2_buffer *v4l2_buf, uint32_t channel)
00235 {
00236 v4l2_buf->timestamp.tv_sec = ts[channel] + time_scale[channel];
00237 ts[channel] += time_scale[channel];
00238
00239 return 1;
00240 }
00241
00242
00243 static nal_type_e
00244 parse_nalu_unit(NvBuffer * buffer)
00245 {
00246 unsigned char *pbuf = buffer->planes[0].data;
00247
00248 return (nal_type_e)(*(pbuf + 4) & 0x1F);
00249 }
00250
00251 static int
00252 wait_for_nextFrame(context_t * ctx)
00253 {
00254 if (ctx->cpu_occupation_option == PARSER_DECODER_VIC_RENDER)
00255 return 1;
00256
00257 pthread_mutex_lock(&ctx->fps_lock);
00258 uint64_t decode_time_usec;
00259 uint64_t decode_time_sec;
00260 uint64_t decode_time_nsec;
00261 struct timespec last_decode_time;
00262 struct timeval now;
00263 gettimeofday(&now, NULL);
00264
00265 last_decode_time.tv_sec = now.tv_sec;
00266 last_decode_time.tv_nsec = now.tv_usec * 1000L;
00267
00268 decode_time_usec = 1000000L / ctx->fps;
00269 decode_time_sec = decode_time_usec / 1000000;
00270 decode_time_nsec = (decode_time_usec % 1000000) * 1000L;
00271
00272 last_decode_time.tv_sec += decode_time_sec;
00273 last_decode_time.tv_nsec += decode_time_nsec;
00274 last_decode_time.tv_sec += last_decode_time.tv_nsec / 1000000000UL;
00275 last_decode_time.tv_nsec %= 1000000000UL;
00276
00277 pthread_cond_timedwait(&ctx->fps_cond, &ctx->fps_lock,
00278 &last_decode_time);
00279 pthread_mutex_unlock(&ctx->fps_lock);
00280
00281 return 1;
00282 }
00283
00284 static bool
00285 conv_output_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
00286 NvBuffer * buffer, NvBuffer * shared_buffer,
00287 void *arg)
00288 {
00289 context_t *ctx = (context_t *) arg;
00290 struct v4l2_buffer dec_capture_ret_buffer;
00291 struct v4l2_plane planes[MAX_PLANES];
00292
00293 memset(&dec_capture_ret_buffer, 0, sizeof(dec_capture_ret_buffer));
00294 memset(planes, 0, sizeof(planes));
00295
00296 dec_capture_ret_buffer.index = shared_buffer->index;
00297 dec_capture_ret_buffer.m.planes = planes;
00298
00299 pthread_mutex_lock(&ctx->queue_lock);
00300 ctx->conv_output_plane_buf_queue->push(buffer);
00301
00302
00303
00304 if (ctx->dec->capture_plane.qBuffer(dec_capture_ret_buffer, NULL) < 0)
00305 {
00306 pthread_cond_broadcast(&ctx->queue_cond);
00307 pthread_mutex_unlock(&ctx->queue_lock);
00308 return false;
00309 }
00310
00311 pthread_cond_broadcast(&ctx->queue_cond);
00312 pthread_mutex_unlock(&ctx->queue_lock);
00313
00314 return true;
00315 }
00316
00317 #ifdef ENABLE_GIE
00318 static bool
00319 conv1_output_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
00320 NvBuffer * buffer, NvBuffer * shared_buffer,
00321 void *arg)
00322 {
00323 context_t *ctx = (context_t *) arg;
00324
00325 pthread_mutex_lock(&ctx->queue1_lock);
00326 ctx->conv1_output_plane_buf_queue->push(buffer);
00327
00328 pthread_cond_broadcast(&ctx->queue1_cond);
00329 pthread_mutex_unlock(&ctx->queue1_lock);
00330
00331 return true;
00332 }
00333 #endif
00334
00335 static void *render_thread(void* arg)
00336 {
00337 context_t *ctx = (context_t *) arg;
00338 Shared_Buffer gie_buffer;
00339 #ifdef ENABLE_GIE
00340 frame_bbox *bbox = NULL;
00341 frame_bbox temp_bbox;
00342 temp_bbox.g_rect_num = 0;
00343 temp_bbox.g_rect = new NvOSD_RectParams[OSD_BUF_NUM];
00344 #endif
00345 while (1)
00346 {
00347
00348 pthread_mutex_lock(&ctx->render_lock);
00349 if (ctx->render_buf_queue->empty())
00350 {
00351 if (ctx->stop_render)
00352 {
00353 pthread_mutex_unlock(&ctx->render_lock);
00354 break;
00355 }
00356 else
00357 {
00358
00359 struct timespec timeout;
00360 timeout.tv_sec = time(0) + 3;
00361 timeout.tv_nsec = 0;
00362 int ret = pthread_cond_timedwait(&ctx->render_cond,
00363 &ctx->render_lock, &timeout);
00364
00365 if (ret != 0)
00366 {
00367 pthread_mutex_unlock(&ctx->render_lock);
00368 break;
00369 }
00370
00371 if (ctx->render_buf_queue->empty())
00372 {
00373 pthread_mutex_unlock(&ctx->render_lock);
00374 break;
00375 }
00376 }
00377 }
00378
00379 gie_buffer = ctx->render_buf_queue->front();
00380 ctx->render_buf_queue->pop();
00381 pthread_mutex_unlock(&ctx->render_lock);
00382
00383 struct v4l2_buffer *v4l2_buf = &gie_buffer.v4l2_buf;
00384 NvBuffer *buffer = gie_buffer.buffer;
00385
00386 if (ctx->cpu_occupation_option != PARSER_DECODER_VIC)
00387 {
00388 #ifndef ENABLE_GIE
00389
00390 ctx->egl_image = NvEGLImageFromFd(egl_display,
00391 buffer->planes[0].fd);
00392 if (ctx->egl_image == NULL)
00393 {
00394 cerr << "Error while mapping dmabuf fd (" <<
00395 buffer->planes[0].fd << ") to EGLImage" << endl;
00396 return NULL;
00397 }
00398
00399
00400 HandleEGLImage(&ctx->egl_image);
00401
00402
00403 NvDestroyEGLImage(egl_display, ctx->egl_image);
00404 ctx->egl_image = NULL;
00405 #else
00406
00407 if (gie_buffer.bProcess == 1)
00408 {
00409 sem_wait(&ctx->result_ready_sem);
00410 pthread_mutex_lock(&ctx->osd_lock);
00411 if (ctx->osd_queue->size() != 0)
00412 {
00413 bbox = ctx->osd_queue->front();
00414 if (bbox != NULL)
00415 {
00416 temp_bbox.g_rect_num = bbox->g_rect_num;
00417 memcpy(temp_bbox.g_rect, bbox->g_rect,
00418 OSD_BUF_NUM * sizeof(NvOSD_RectParams));
00419 delete []bbox->g_rect;
00420 delete bbox;
00421 bbox = NULL;
00422 }
00423 ctx->osd_queue->pop();
00424 }
00425 pthread_mutex_unlock(&ctx->osd_lock);
00426 }
00427
00428 if (temp_bbox.g_rect_num != 0)
00429 {
00430 nvosd_draw_rectangles(ctx->nvosd_context, MODE_HW,
00431 buffer->planes[0].fd, temp_bbox.g_rect_num, temp_bbox.g_rect);
00432 }
00433 #endif
00434
00435 ctx->renderer->render(buffer->planes[0].fd);
00436
00437
00438 if (ctx->out_file)
00439 write_video_frame(ctx->out_file, *buffer);
00440 }
00441
00442 if (ctx->conv->capture_plane.qBuffer(*v4l2_buf, NULL) < 0)
00443 {
00444 return NULL;
00445 }
00446 }
00447 #ifdef ENABLE_GIE
00448 delete []temp_bbox.g_rect;
00449 #endif
00450 return NULL;
00451 }
00452
00453 static bool
00454 conv_capture_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
00455 NvBuffer * buffer,
00456 NvBuffer * shared_buffer,
00457 void *arg)
00458 {
00459 context_t *ctx = (context_t *) arg;
00460 Shared_Buffer batch_buffer;
00461 batch_buffer.bProcess = 0;
00462 #ifdef ENABLE_GIE
00463
00464 if (ctx->channel < g_gie_context.getNumGieInstances() &&
00465 (frame_num++ % g_gie_context.getFilterNum()) == 0)
00466 {
00467 int ret;
00468 struct v4l2_buffer conv_capture_ret_buffer;
00469 struct v4l2_plane planes[MAX_PLANES];
00470
00471 memset(&conv_capture_ret_buffer, 0, sizeof(conv_capture_ret_buffer));
00472 memset(planes, 0, sizeof(planes));
00473
00474 NvBuffer *conv1_buffer;
00475 pthread_mutex_lock(&ctx->queue1_lock);
00476 while (ctx->conv1_output_plane_buf_queue->empty())
00477 {
00478 pthread_cond_wait(&ctx->queue1_cond, &ctx->queue1_lock);
00479 }
00480 conv1_buffer = ctx->conv1_output_plane_buf_queue->front();
00481 ctx->conv1_output_plane_buf_queue->pop();
00482 pthread_mutex_unlock(&ctx->queue1_lock);
00483 conv_capture_ret_buffer.index = conv1_buffer->index;
00484 conv_capture_ret_buffer.m.planes = planes;
00485
00486 ret = ctx->conv1->output_plane.qBuffer(conv_capture_ret_buffer,
00487 buffer);
00488 if (ret < 0)
00489 {
00490 ctx->got_error = true;
00491 return false;
00492 }
00493 batch_buffer.bProcess = 1;
00494 }
00495 #endif
00496
00497
00498
00499
00500 memcpy(&batch_buffer.v4l2_buf, v4l2_buf, sizeof(v4l2_buffer));
00501
00502 batch_buffer.buffer = buffer;
00503 batch_buffer.shared_buffer = shared_buffer;
00504 batch_buffer.arg = arg;
00505 pthread_mutex_lock(&ctx->render_lock);
00506 ctx->render_buf_queue->push(batch_buffer);
00507 pthread_cond_broadcast(&ctx->render_cond);
00508 pthread_mutex_unlock(&ctx->render_lock);
00509
00510 return true;
00511 }
00512
00513
00514 #ifdef ENABLE_GIE
00515 void *gie_thread(void *data)
00516 {
00517 int buf_num = 0;
00518 EGLImageKHR egl_image = NULL;
00519 struct v4l2_buffer *v4l2_buf;
00520 NvBuffer *buffer;
00521 NvBuffer *shared_buffer;
00522 context_t *ctx;
00523 int process_last_batch = 0;
00524 float *gie_inputbuf = g_gie_context.getInputBuf();
00525
00526 while (1)
00527 {
00528
00529 Shared_Buffer gie_buffer;
00530 pthread_mutex_lock(&GIE_lock);
00531 if(GIE_Buffer_Queue.empty())
00532 {
00533 if (GIE_Stop)
00534 {
00535 pthread_mutex_unlock(&GIE_lock);
00536 break;
00537 }
00538 else
00539 {
00540
00541 struct timespec timeout;
00542 timeout.tv_sec = time(0) + 3;
00543 timeout.tv_nsec = 0;
00544 int ret =
00545 pthread_cond_timedwait(&GIE_cond, &GIE_lock, &timeout);
00546 if (ret != 0)
00547 {
00548 cout << "Timedout waiting for input data"<<endl;
00549 }
00550 }
00551 }
00552 if (GIE_Buffer_Queue.size() != 0)
00553 {
00554 gie_buffer = GIE_Buffer_Queue.front();
00555 GIE_Buffer_Queue.pop();
00556 }
00557 else
00558 {
00559 process_last_batch = 1;
00560 }
00561 pthread_mutex_unlock(&GIE_lock);
00562
00563 if (process_last_batch == 0)
00564 {
00565 v4l2_buf = &gie_buffer.v4l2_buf;
00566 buffer = gie_buffer.buffer;
00567 shared_buffer = gie_buffer.shared_buffer;
00568 ctx = (context_t *)gie_buffer.arg;
00569
00570 int batch_offset = buf_num * g_gie_context.getNetWidth() *
00571 g_gie_context.getNetHeight() * g_gie_context.getChannel();
00572 #if USE_CPU_FOR_INTFLOAT_CONVERSION
00573
00574
00575
00576 unsigned char *data = buffer->planes[0].data;
00577 int channel_offset = g_gie_context.getNetWidth() *
00578 g_gie_context.getNetHeight();
00579
00580 for (int i = 0; i < g_gie_context.getChannel(); i++)
00581 {
00582 for (int j = 0; j < g_gie_context.getNetHeight(); j++)
00583 {
00584 for (int k = 0; k < g_gie_context.getNetWidth(); k++)
00585 {
00586 int total_offset = batch_offset + channel_offset * i +
00587 j * g_gie_context.getNetWidth() + k;
00588 gie_inputbuf[total_offset] =
00589 (float)(*(data + j * buffer->planes[0].fmt.stride
00590 + k * 4 + 3 - i - 1));
00591 }
00592 }
00593 }
00594 #else
00595
00596
00597 egl_image = NvEGLImageFromFd(egl_display,
00598 buffer->planes[0].fd);
00599 if (egl_image == NULL)
00600 {
00601 cerr << "Error while mapping dmabuf fd (" <<
00602 buffer->planes[0].fd << ") to EGLImage" << endl;
00603 return NULL;
00604 }
00605
00606 void *cuda_buf = g_gie_context.getBuffer(0);
00607
00608 mapEGLImage2Float(&egl_image, g_gie_context.getNetWidth(),
00609 g_gie_context.getNetHeight(),
00610 (char *)cuda_buf +
00611 batch_offset * sizeof(float));
00612
00613
00614 NvDestroyEGLImage(egl_display, egl_image);
00615 egl_image = NULL;
00616 #endif
00617 buf_num++;
00618
00619 if (ctx->conv1->capture_plane.qBuffer(*v4l2_buf, NULL) < 0)
00620 {
00621 cout<<"conv1 queue buffer error"<<endl;
00622 }
00623
00624 if (buf_num < g_gie_context.getBatchSize())
00625 {
00626 continue;
00627 }
00628 }
00629
00630 else if(buf_num == 0)
00631 {
00632 break;
00633 }
00634
00635
00636 buf_num = 0;
00637 queue<vector<cv::Rect>> rectList_queue;
00638 #if USE_CPU_FOR_INTFLOAT_CONVERSION
00639 g_gie_context.doInference(
00640 rectList_queue, gie_inputbuf);
00641 #else
00642 g_gie_context.doInference(
00643 rectList_queue);
00644 #endif
00645
00646 while(!rectList_queue.empty())
00647 {
00648 vector<cv::Rect> rectList = rectList_queue.front();
00649 rectList_queue.pop();
00650 frame_bbox *bbox = new frame_bbox;
00651 bbox->g_rect_num = 0;
00652 bbox->g_rect = new NvOSD_RectParams[OSD_BUF_NUM];
00653 for (int i = 0; i < rectList.size(); i++)
00654 {
00655 cv::Rect &r = rectList[i];
00656 if ((r.width * IMAGE_WIDTH / g_gie_context.getNetWidth() < 10) ||
00657 (r.height * IMAGE_HEIGHT / g_gie_context.getNetHeight() < 10))
00658 continue;
00659 bbox->g_rect[bbox->g_rect_num].left =
00660 (unsigned int) (r.x * IMAGE_WIDTH / g_gie_context.getNetWidth());
00661 bbox->g_rect[bbox->g_rect_num].top =
00662 (unsigned int) (r.y * IMAGE_HEIGHT / g_gie_context.getNetHeight());
00663 bbox->g_rect[bbox->g_rect_num].width =
00664 (unsigned int) (r.width * IMAGE_WIDTH / g_gie_context.getNetWidth());
00665 bbox->g_rect[bbox->g_rect_num].height =
00666 (unsigned int) (r.height * IMAGE_HEIGHT / g_gie_context.getNetHeight());
00667
00668 bbox->g_rect[bbox->g_rect_num].border_width = 5;
00669 bbox->g_rect[bbox->g_rect_num].has_bg_color = 0;
00670 bbox->g_rect[bbox->g_rect_num].border_color.red = 1.0f;
00671 bbox->g_rect[bbox->g_rect_num].border_color.green = 0.0;
00672 bbox->g_rect[bbox->g_rect_num].border_color.blue = 0.0;
00673 bbox->g_rect_num++;
00674 }
00675 pthread_mutex_lock(&ctx->osd_lock);
00676 ctx->osd_queue->push(bbox);
00677 pthread_mutex_unlock(&ctx->osd_lock);
00678
00679 sem_post(&ctx->result_ready_sem);
00680 }
00681 if (process_last_batch == 1)
00682 {
00683 break;
00684 }
00685 }
00686
00687 return NULL;
00688 }
00689
00690 static bool
00691 conv1_capture_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
00692 NvBuffer *buffer,
00693 NvBuffer *shared_buffer,
00694 void *arg)
00695 {
00696
00697 Shared_Buffer gie_buffer;
00698
00699
00700
00701
00702 memcpy(&gie_buffer.v4l2_buf, v4l2_buf, sizeof(v4l2_buffer));
00703
00704 gie_buffer.buffer = buffer;
00705 gie_buffer.shared_buffer = shared_buffer;
00706 gie_buffer.arg = arg;
00707 pthread_mutex_lock(&GIE_lock);
00708 GIE_Buffer_Queue.push(gie_buffer);
00709 pthread_cond_broadcast(&GIE_cond);
00710 pthread_mutex_unlock(&GIE_lock);
00711
00712 return true;
00713 }
00714 #endif
00715
00716 static void
00717 query_and_set_capture(context_t * ctx)
00718 {
00719 NvVideoDecoder *dec = ctx->dec;
00720 struct v4l2_format format;
00721 struct v4l2_crop crop;
00722 int32_t min_dec_capture_buffers;
00723 int ret = 0;
00724 int error = 0;
00725 uint32_t window_width;
00726 uint32_t window_height;
00727 char OSDcontent[512];
00728
00729
00730
00731 ret = dec->capture_plane.getFormat(format);
00732 TEST_ERROR(ret < 0,
00733 "Error: Could not get format from decoder capture plane", error);
00734
00735
00736 ret = dec->capture_plane.getCrop(crop);
00737 TEST_ERROR(ret < 0,
00738 "Error: Could not get crop from decoder capture plane", error);
00739
00740 if (ctx->cpu_occupation_option == PARSER_DECODER_VIC_RENDER)
00741 {
00742
00743 delete ctx->renderer;
00744
00745 if (ctx->fullscreen)
00746 {
00747
00748 window_width = window_height = 0;
00749 }
00750 else if (ctx->window_width && ctx->window_height)
00751 {
00752
00753 window_width = ctx->window_width;
00754 window_height = ctx->window_height;
00755 }
00756 else
00757 {
00758
00759 window_width = crop.c.width;
00760 window_height = crop.c.height;
00761 }
00762
00763
00764
00765 ctx->renderer =
00766 NvEglRenderer::createEglRenderer("renderer0", window_width,
00767 window_height, ctx->window_x,
00768 ctx->window_y);
00769 TEST_ERROR(!ctx->renderer,
00770 "Error in setting up renderer. "
00771 "Check if X is running or run with --disable-rendering",
00772 error);
00773
00774 ctx->renderer->setFPS(ctx->fps);
00775 #ifndef ENABLE_GIE
00776 sprintf(OSDcontent, "Channel:%d", ctx->channel);
00777 ctx->renderer->setOverlayText(OSDcontent, 800, 50);
00778 #endif
00779 }
00780
00781
00782 dec->capture_plane.deinitPlane();
00783
00784
00785
00786 ret = dec->setCapturePlaneFormat(format.fmt.pix_mp.pixelformat,
00787 format.fmt.pix_mp.width,
00788 format.fmt.pix_mp.height);
00789 TEST_ERROR(ret < 0, "Error in setting decoder capture plane format",
00790 error);
00791
00792
00793 ret =
00794 dec->getControl(V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
00795 min_dec_capture_buffers);
00796 TEST_ERROR(ret < 0,
00797 "Error while getting value for V4L2_CID_MIN_BUFFERS_FOR_CAPTURE",
00798 error);
00799
00800
00801 ret =
00802 dec->capture_plane.setupPlane(V4L2_MEMORY_MMAP,
00803 min_dec_capture_buffers + 5, false,
00804 false);
00805 TEST_ERROR(ret < 0, "Error in decoder capture plane setup", error);
00806
00807
00808
00809
00810 ctx->conv->waitForIdle(1000);
00811 ctx->conv->output_plane.stopDQThread();
00812 ctx->conv->capture_plane.stopDQThread();
00813
00814 ctx->conv->output_plane.deinitPlane();
00815 ctx->conv->capture_plane.deinitPlane();
00816 #ifdef ENABLE_GIE
00817 if (ctx->channel < g_gie_context.getNumGieInstances())
00818 {
00819 ctx->conv1->waitForIdle(1000);
00820 ctx->conv1->output_plane.stopDQThread();
00821 ctx->conv1->capture_plane.stopDQThread();
00822
00823 ctx->conv1->output_plane.deinitPlane();
00824 ctx->conv1->capture_plane.deinitPlane();
00825 }
00826 #endif
00827 while(!ctx->conv_output_plane_buf_queue->empty())
00828 {
00829 ctx->conv_output_plane_buf_queue->pop();
00830 }
00831 #ifdef ENABLE_GIE
00832 if (ctx->channel < g_gie_context.getNumGieInstances())
00833 {
00834 while(!ctx->conv1_output_plane_buf_queue->empty())
00835 {
00836 ctx->conv1_output_plane_buf_queue->pop();
00837 }
00838 }
00839 #endif
00840 ret = ctx->conv->setOutputPlaneFormat(format.fmt.pix_mp.pixelformat,
00841 format.fmt.pix_mp.width,
00842 format.fmt.pix_mp.height,
00843 V4L2_NV_BUFFER_LAYOUT_BLOCKLINEAR);
00844 TEST_ERROR(ret < 0, "Error in converter output plane set format",
00845 error);
00846
00847 ret = ctx->conv->setCapturePlaneFormat(format.fmt.pix_mp.pixelformat,
00848 crop.c.width,
00849 crop.c.height,
00850 V4L2_NV_BUFFER_LAYOUT_PITCH);
00851 TEST_ERROR(ret < 0, "Error in converter capture plane set format",
00852 error);
00853
00854 ret = ctx->conv->setCropRect(0, 0, crop.c.width, crop.c.height);
00855 TEST_ERROR(ret < 0, "Error while setting crop rect", error);
00856
00857 #ifdef ENABLE_GIE
00858 if (ctx->channel < g_gie_context.getNumGieInstances())
00859 {
00860 ret = ctx->conv1->setOutputPlaneFormat(format.fmt.pix_mp.pixelformat,
00861 crop.c.width,
00862 crop.c.height,
00863 V4L2_NV_BUFFER_LAYOUT_PITCH);
00864 TEST_ERROR(ret < 0, "Error in converter output plane set format",
00865 error);
00866
00867 ret = ctx->conv1->setCapturePlaneFormat(V4L2_PIX_FMT_ABGR32,
00868 g_gie_context.getNetWidth(),
00869 g_gie_context.getNetHeight(),
00870 V4L2_NV_BUFFER_LAYOUT_PITCH);
00871 TEST_ERROR(ret < 0, "Error in converter capture plane set format",
00872 error);
00873 }
00874 #endif
00875
00876 ret =
00877 ctx->conv->output_plane.setupPlane(V4L2_MEMORY_DMABUF,
00878 dec->capture_plane.
00879 getNumBuffers(), false, false);
00880 TEST_ERROR(ret < 0, "Error in converter output plane setup", error);
00881
00882 ret =
00883 ctx->conv->capture_plane.setupPlane(V4L2_MEMORY_MMAP,
00884 dec->capture_plane.
00885 getNumBuffers(), true, false);
00886 TEST_ERROR(ret < 0, "Error in converter capture plane setup", error);
00887 #ifdef ENABLE_GIE
00888 if (ctx->channel < g_gie_context.getNumGieInstances())
00889 {
00890 ret =
00891 ctx->conv1->output_plane.setupPlane(V4L2_MEMORY_DMABUF,
00892 dec->capture_plane.
00893 getNumBuffers(), false, false);
00894 TEST_ERROR(ret < 0, "Error in converter output plane setup", error);
00895
00896 ret =
00897 ctx->conv1->capture_plane.setupPlane(V4L2_MEMORY_MMAP,
00898 dec->capture_plane.
00899 getNumBuffers(), true, false);
00900 TEST_ERROR(ret < 0, "Error in converter capture plane setup", error);
00901 }
00902 #endif
00903 ret = ctx->conv->output_plane.setStreamStatus(true);
00904 TEST_ERROR(ret < 0, "Error in converter output plane streamon", error);
00905
00906 ret = ctx->conv->capture_plane.setStreamStatus(true);
00907 TEST_ERROR(ret < 0, "Error in converter output plane streamoff",
00908 error);
00909 #ifdef ENABLE_GIE
00910 if (ctx->channel < g_gie_context.getNumGieInstances())
00911 {
00912 ret = ctx->conv1->output_plane.setStreamStatus(true);
00913 TEST_ERROR(ret < 0, "Error in converter output plane streamon", error);
00914
00915 ret = ctx->conv1->capture_plane.setStreamStatus(true);
00916 TEST_ERROR(ret < 0, "Error in converter output plane streamoff",
00917 error);
00918 }
00919 #endif
00920
00921 for (uint32_t i = 0; i < ctx->conv->output_plane.getNumBuffers(); i++)
00922 {
00923 ctx->conv_output_plane_buf_queue->push(ctx->conv->output_plane.
00924 getNthBuffer(i));
00925 }
00926
00927 #ifdef ENABLE_GIE
00928 if (ctx->channel < g_gie_context.getNumGieInstances())
00929 {
00930
00931 for (uint32_t i = 0; i < ctx->conv1->output_plane.getNumBuffers(); i++)
00932 {
00933 ctx->conv1_output_plane_buf_queue->push(ctx->conv1->output_plane.
00934 getNthBuffer(i));
00935 }
00936 }
00937 #endif
00938 for (uint32_t i = 0; i < ctx->conv->capture_plane.getNumBuffers(); i++)
00939 {
00940 struct v4l2_buffer v4l2_buf;
00941 struct v4l2_plane planes[MAX_PLANES];
00942
00943 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00944 memset(planes, 0, sizeof(planes));
00945
00946 v4l2_buf.index = i;
00947 v4l2_buf.m.planes = planes;
00948 ret = ctx->conv->capture_plane.qBuffer(v4l2_buf, NULL);
00949 TEST_ERROR(ret < 0, "Error Qing buffer at converter output plane",
00950 error);
00951 }
00952
00953 #ifdef ENABLE_GIE
00954 if (ctx->channel < g_gie_context.getNumGieInstances())
00955 {
00956 for (uint32_t i = 0; i < ctx->conv1->capture_plane.getNumBuffers();
00957 i++)
00958 {
00959 struct v4l2_buffer v4l2_buf;
00960 struct v4l2_plane planes[MAX_PLANES];
00961
00962 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00963 memset(planes, 0, sizeof(planes));
00964
00965 v4l2_buf.index = i;
00966 v4l2_buf.m.planes = planes;
00967 ret = ctx->conv1->capture_plane.qBuffer(v4l2_buf, NULL);
00968 TEST_ERROR(ret < 0, "Error Qing buffer at converter output plane",
00969 error);
00970 }
00971 }
00972 #endif
00973 ctx->conv->output_plane.startDQThread(ctx);
00974 ctx->conv->capture_plane.startDQThread(ctx);
00975 #ifdef ENABLE_GIE
00976 if (ctx->channel < g_gie_context.getNumGieInstances())
00977 {
00978 ctx->conv1->output_plane.startDQThread(ctx);
00979 ctx->conv1->capture_plane.startDQThread(ctx);
00980 }
00981 #endif
00982
00983 ret = dec->capture_plane.setStreamStatus(true);
00984 TEST_ERROR(ret < 0, "Error in decoder capture plane streamon", error);
00985
00986
00987 for (uint32_t i = 0; i < dec->capture_plane.getNumBuffers(); i++)
00988 {
00989 struct v4l2_buffer v4l2_buf;
00990 struct v4l2_plane planes[MAX_PLANES];
00991
00992 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00993 memset(planes, 0, sizeof(planes));
00994
00995 v4l2_buf.index = i;
00996 v4l2_buf.m.planes = planes;
00997 ret = dec->capture_plane.qBuffer(v4l2_buf, NULL);
00998 TEST_ERROR(ret < 0, "Error Qing buffer at output plane", error);
00999 }
01000 cout << "Query and set capture successful" << endl;
01001 return;
01002
01003 error:
01004 if (error)
01005 {
01006 ctx->got_error = true;
01007 cerr << "Error in " << __func__ << endl;
01008 }
01009 }
01010
01011 static void *
01012 dec_capture_loop_fcn(void *arg)
01013 {
01014 context_t *ctx = (context_t *) arg;
01015 NvVideoDecoder *dec = ctx->dec;
01016 map<uint64_t, frame_info_t*>::iterator iter;
01017 struct v4l2_event ev;
01018 int ret;
01019
01020 cout << "Starting decoder capture loop thread" << endl;
01021
01022
01023
01024 do
01025 {
01026 ret = dec->dqEvent(ev, 1000);
01027 if (ret < 0)
01028 {
01029 if (errno == EAGAIN)
01030 {
01031 cerr <<
01032 "Timed out waiting for first V4L2_EVENT_RESOLUTION_CHANGE"
01033 << endl;
01034 }
01035 else
01036 {
01037 cerr << "Error in dequeueing decoder event" << endl;
01038 }
01039 ctx->got_error = true;
01040 break;
01041 }
01042 }
01043 while (ev.type != V4L2_EVENT_RESOLUTION_CHANGE);
01044
01045
01046 if (!ctx->got_error)
01047 query_and_set_capture(ctx);
01048
01049
01050 while (!(ctx->got_error || dec->isInError() || ctx->got_eos))
01051 {
01052 NvBuffer *dec_buffer;
01053
01054
01055 ret = dec->dqEvent(ev, false);
01056 if (ret == 0)
01057 {
01058 switch (ev.type)
01059 {
01060 case V4L2_EVENT_RESOLUTION_CHANGE:
01061 query_and_set_capture(ctx);
01062 continue;
01063 }
01064 }
01065
01066 while (1)
01067 {
01068 struct v4l2_buffer v4l2_buf;
01069 struct v4l2_plane planes[MAX_PLANES];
01070
01071 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
01072 memset(planes, 0, sizeof(planes));
01073 v4l2_buf.m.planes = planes;
01074
01075
01076 if (dec->capture_plane.dqBuffer(v4l2_buf, &dec_buffer, NULL, 0))
01077 {
01078 if (errno == EAGAIN)
01079 {
01080 usleep(1000);
01081 }
01082 else
01083 {
01084 ctx->got_error = true;
01085 cerr << "Error while calling dequeue at capture plane" <<
01086 endl;
01087 }
01088 break;
01089 }
01090
01091 if (ctx->do_stat)
01092 {
01093 iter = ctx->frame_info_map->find(v4l2_buf.timestamp.tv_sec);
01094 if (iter == ctx->frame_info_map->end())
01095 {
01096 cout<<"image not return by decoder"<<endl;
01097 }
01098 else
01099 {
01100 gettimeofday(&iter->second->output_time, NULL);
01101 }
01102 }
01103
01104 if (ctx->cpu_occupation_option == PARSER_DECODER)
01105 {
01106
01107 if (dec->capture_plane.qBuffer(v4l2_buf, NULL) < 0)
01108 {
01109 ctx->got_error = true;
01110 cerr <<
01111 "Error while queueing buffer at decoder capture plane"
01112 << endl;
01113 break;
01114 }
01115 continue;
01116 }
01117
01118
01119 NvBuffer *conv_buffer;
01120 struct v4l2_buffer conv_output_buffer;
01121 struct v4l2_plane conv_planes[MAX_PLANES];
01122
01123 memset(&conv_output_buffer, 0, sizeof(conv_output_buffer));
01124 memset(conv_planes, 0, sizeof(conv_planes));
01125 conv_output_buffer.m.planes = conv_planes;
01126
01127
01128 pthread_mutex_lock(&ctx->queue_lock);
01129 while (ctx->conv_output_plane_buf_queue->empty())
01130 {
01131 pthread_cond_wait(&ctx->queue_cond, &ctx->queue_lock);
01132 }
01133 conv_buffer = ctx->conv_output_plane_buf_queue->front();
01134 ctx->conv_output_plane_buf_queue->pop();
01135 pthread_mutex_unlock(&ctx->queue_lock);
01136
01137 conv_output_buffer.index = conv_buffer->index;
01138
01139 if (ctx->conv->output_plane.
01140 qBuffer(conv_output_buffer, dec_buffer) < 0)
01141 {
01142 ctx->got_error = true;
01143 cerr <<
01144 "Error while queueing buffer at converter output plane"
01145 << endl;
01146 break;
01147 }
01148
01149 }
01150 }
01151
01152 cout << "Exiting decoder capture loop thread" << endl;
01153
01154 ctx->got_eos = true;
01155
01156
01157 sem_post(&(ctx->dec_run_sem));
01158 return NULL;
01159 }
01160
01161 static void *
01162 dec_feed_loop_fcn(void *arg)
01163 {
01164 context_t *ctx = (context_t *) arg;
01165 int i = 0;
01166 bool eos = false;
01167 int ret;
01168 char *nalu_parse_buffer = NULL;
01169 nal_type_e nal_type;
01170
01171 if (ctx->input_nalu)
01172 {
01173 nalu_parse_buffer = new char[CHUNK_SIZE];
01174 }
01175
01176
01177
01178 while (!eos && !ctx->got_error && !ctx->dec->isInError() &&
01179 i < (int)ctx->dec->output_plane.getNumBuffers())
01180 {
01181 struct v4l2_buffer v4l2_buf;
01182 struct v4l2_plane planes[MAX_PLANES];
01183 NvBuffer *buffer;
01184
01185 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
01186 memset(planes, 0, sizeof(planes));
01187
01188 buffer = ctx->dec->output_plane.getNthBuffer(i);
01189 if (ctx->input_nalu)
01190 {
01191 read_decoder_input_nalu(ctx->in_file, buffer,
01192 nalu_parse_buffer, CHUNK_SIZE);
01193 wait_for_nextFrame(ctx);
01194 if (ctx->cpu_occupation_option == PARSER)
01195 {
01196 if (buffer->planes[0].bytesused == 0)
01197 {
01198 cout<<"Input file read complete"<<endl;
01199
01200 sem_post(&(ctx->dec_run_sem));
01201 return NULL;
01202 }
01203 else
01204 continue;
01205 }
01206 }
01207 else
01208 {
01209 read_decoder_input_chunk(ctx->in_file, buffer);
01210 }
01211
01212 v4l2_buf.index = i;
01213 if (ctx->input_nalu && ctx->do_stat)
01214 {
01215 nal_type = parse_nalu_unit(buffer);
01216 switch (nal_type)
01217 {
01218 case NAL_UNIT_CODED_SLICE:
01219 case NAL_UNIT_CODED_SLICE_DATAPART_A:
01220 case NAL_UNIT_CODED_SLICE_DATAPART_B:
01221 case NAL_UNIT_CODED_SLICE_DATAPART_C:
01222 case NAL_UNIT_CODED_SLICE_IDR:
01223 {
01224 assign_decode_ts(&v4l2_buf, ctx->channel);
01225 frame_info_t *frame_meta = new frame_info_t;
01226 memset(frame_meta, 0, sizeof(frame_info_t));
01227
01228 frame_meta->timestamp = v4l2_buf.timestamp.tv_sec;
01229 gettimeofday(&frame_meta->input_time, NULL);
01230 frame_meta->nal_type = nal_type;
01231
01232 ctx->frame_info_map->insert(
01233 pair< uint64_t, frame_info_t* >(
01234 v4l2_buf.timestamp.tv_sec, frame_meta));
01235 break;
01236 }
01237 default:
01238 break;
01239 }
01240 }
01241 v4l2_buf.m.planes = planes;
01242 v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;
01243
01244
01245 ret = ctx->dec->output_plane.qBuffer(v4l2_buf, NULL);
01246 if (ret < 0)
01247 {
01248 cerr << "Error Qing buffer at output plane" << endl;
01249 ctx->got_error = true;
01250 break;
01251 }
01252 if (v4l2_buf.m.planes[0].bytesused == 0)
01253 {
01254 eos = true;
01255 cout << "Input file read complete" << endl;
01256 break;
01257 }
01258 i++;
01259 }
01260
01261
01262
01263
01264 while (!eos && !ctx->got_error && !ctx->dec->isInError())
01265 {
01266 struct v4l2_buffer v4l2_buf;
01267 struct v4l2_plane planes[MAX_PLANES];
01268 NvBuffer *buffer;
01269
01270 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
01271 memset(planes, 0, sizeof(planes));
01272 v4l2_buf.m.planes = planes;
01273
01274 ret = ctx->dec->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, -1);
01275 if (ret < 0)
01276 {
01277 cerr << "Error DQing buffer at output plane" << endl;
01278 ctx->got_error = true;
01279 break;
01280 }
01281
01282 if (ctx->input_nalu)
01283 {
01284 read_decoder_input_nalu(ctx->in_file, buffer,
01285 nalu_parse_buffer, CHUNK_SIZE);
01286 wait_for_nextFrame(ctx);
01287 }
01288 else
01289 {
01290 read_decoder_input_chunk(ctx->in_file, buffer);
01291 }
01292
01293 if (ctx->input_nalu && ctx->do_stat)
01294 {
01295 nal_type = parse_nalu_unit(buffer);
01296 switch (nal_type)
01297 {
01298 case NAL_UNIT_CODED_SLICE:
01299 case NAL_UNIT_CODED_SLICE_DATAPART_A:
01300 case NAL_UNIT_CODED_SLICE_DATAPART_B:
01301 case NAL_UNIT_CODED_SLICE_DATAPART_C:
01302 case NAL_UNIT_CODED_SLICE_IDR:
01303 {
01304 assign_decode_ts(&v4l2_buf, ctx->channel);
01305 frame_info_t *frame_meta = new frame_info_t;
01306 memset(frame_meta, 0, sizeof(frame_info_t));
01307
01308 frame_meta->timestamp = v4l2_buf.timestamp.tv_sec;
01309 gettimeofday(&frame_meta->input_time, NULL);
01310 frame_meta->nal_type = nal_type;
01311 ctx->frame_info_map->insert(
01312 pair< uint64_t, frame_info_t* >(
01313 v4l2_buf.timestamp.tv_sec, frame_meta));
01314 break;
01315 }
01316 default:
01317 break;
01318 }
01319 }
01320 v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;
01321 ret = ctx->dec->output_plane.qBuffer(v4l2_buf, NULL);
01322 if (ret < 0)
01323 {
01324 cerr << "Error Qing buffer at output plane" << endl;
01325 ctx->got_error = true;
01326 break;
01327 }
01328 if (v4l2_buf.m.planes[0].bytesused == 0)
01329 {
01330 eos = true;
01331 cout << "Input file read complete" << endl;
01332 break;
01333 }
01334 }
01335
01336
01337
01338 while (ctx->dec->output_plane.getNumQueuedBuffers() > 0 &&
01339 !ctx->got_error && !ctx->dec->isInError())
01340 {
01341 struct v4l2_buffer v4l2_buf;
01342 struct v4l2_plane planes[MAX_PLANES];
01343
01344 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
01345 memset(planes, 0, sizeof(planes));
01346
01347 v4l2_buf.m.planes = planes;
01348 ret = ctx->dec->output_plane.dqBuffer(v4l2_buf, NULL, NULL, -1);
01349 if (ret < 0)
01350 {
01351 cerr << "Error DQing buffer at output plane" << endl;
01352 ctx->got_error = true;
01353 break;
01354 }
01355 }
01356
01357 if (ctx->input_nalu)
01358 {
01359 delete []nalu_parse_buffer;
01360 }
01361
01362 ctx->got_eos = true;
01363 return NULL;
01364 }
01365
01366 static void
01367 set_defaults(context_t * ctx)
01368 {
01369 memset(ctx, 0, sizeof(context_t));
01370 ctx->fullscreen = false;
01371 ctx->window_height = 0;
01372 ctx->window_width = 0;
01373 ctx->window_x = 0;
01374 ctx->window_y = 0;
01375 ctx->input_nalu = 1;
01376 ctx->fps = 30;
01377 ctx->do_stat = 0;
01378 ctx->cpu_occupation_option = 0;
01379 ctx->dec_status = 0;
01380 ctx->conv_output_plane_buf_queue = new queue < NvBuffer * >;
01381 #ifdef ENABLE_GIE
01382 if (ctx->channel < g_gie_context.getNumGieInstances())
01383 {
01384 ctx->conv1_output_plane_buf_queue = new queue < NvBuffer * >;
01385 }
01386 pthread_mutex_init(&ctx->osd_lock, NULL);
01387 ctx->osd_queue = new queue <frame_bbox*>;
01388 #endif
01389 ctx->render_buf_queue = new queue <Shared_Buffer>;
01390 ctx->stop_render = 0;
01391 ctx->frame_info_map = new map< uint64_t, frame_info_t* >;
01392 ctx->nvosd_context = NULL;
01393 }
01394
01395 #ifdef ENABLE_GIE
01396 static void
01397 set_globalcfg_default(global_cfg *cfg)
01398 {
01399 cfg->deployfile = GOOGLE_NET_DEPLOY_NAME;
01400 cfg->modelfile = GOOGLE_NET_MODEL_NAME;
01401 }
01402 #endif
01403
01404 static void
01405 get_disp_resolution(display_resolution_t *res)
01406 {
01407 if (NvEglRenderer::getDisplayResolution(
01408 res->window_width, res->window_height) < 0)
01409 {
01410 cerr << "get resolution failed, program will exit" << endl;
01411 exit(0);
01412 }
01413
01414 return;
01415 }
01416
01417 static void
01418 do_statistic(context_t * ctx)
01419 {
01420 uint64_t accu_latency = 0;
01421 uint64_t accu_frames = 0;
01422 struct timeval start_time;
01423 struct timeval end_time;
01424 map<uint64_t, frame_info_t*>::iterator iter;
01425
01426 for( iter = ctx->frame_info_map->begin();
01427 iter != ctx->frame_info_map->end(); iter++)
01428 {
01429 if (iter->second->output_time.tv_sec != 0 &&
01430 iter->second->input_time.tv_sec != 0)
01431 {
01432 accu_latency += (iter->second->output_time.tv_sec -
01433 iter->second->input_time.tv_sec) * 1000 +
01434 ( iter->second->output_time.tv_usec -
01435 iter->second->input_time.tv_usec ) / 1000;
01436 accu_frames++;
01437 end_time = iter->second->output_time;
01438 }
01439
01440 if (iter == ctx->frame_info_map->begin())
01441 {
01442 start_time = iter->second->input_time;
01443 }
01444 }
01445
01446 cout << "total frames:" << accu_frames<<endl;
01447 cout <<"pipeline:" << ctx->channel << " avg_latency:(ms)" <<
01448 accu_latency / accu_frames << " fps:" <<
01449 accu_frames * 1000000 / (end_time.tv_sec * 1000000 +
01450 end_time.tv_usec - start_time.tv_sec * 1000000 -
01451 start_time.tv_usec ) << endl;
01452 }
01453
01454 int
01455 main(int argc, char *argv[])
01456 {
01457 context_t ctx[CHANNEL_NUM];
01458 global_cfg cfg;
01459 int error = 0;
01460 int iterator;
01461 map<uint64_t, frame_info_t*>::iterator iter;
01462 display_resolution_t disp_info;
01463 char **argp;
01464 memset(&cfg, 0, sizeof(global_cfg));
01465 #ifdef ENABLE_GIE
01466 set_globalcfg_default(&cfg);
01467 #endif
01468
01469 argp = argv;
01470 parse_global(&cfg, argc, &argp);
01471
01472 if (parse_csv_args(&ctx[0],
01473 #ifdef ENABLE_GIE
01474 &g_gie_context,
01475 #endif
01476 argc - cfg.channel_num - 1, argp))
01477 {
01478 fprintf(stderr, "Error parsing commandline arguments\n");
01479 return -1;
01480 }
01481
01482 #ifdef ENABLE_GIE
01483 #if USE_CPU_FOR_INTFLOAT_CONVERSION
01484 g_gie_context.buildGieContext(cfg.deployfile, cfg.modelfile, true);
01485 #else
01486 g_gie_context.buildGieContext(cfg.deployfile, cfg.modelfile);
01487 #endif
01488
01489 if (g_gie_context.getBatchSize() * g_gie_context.getFilterNum() > 10)
01490 {
01491 fprintf(stderr,
01492 "Not enough buffers. Decrease gie-proc-interval and run again. Exiting\n");
01493 #if USE_CPU_FOR_INTFLOAT_CONVERSION
01494 g_gie_context.destroyGieContext(true);
01495 #else
01496 g_gie_context.destroyGieContext();
01497 #endif
01498 return 0;
01499 }
01500 pthread_create(&GIE_Thread_handle, NULL, gie_thread, NULL);
01501 #endif
01502
01503 get_disp_resolution(&disp_info);
01504 init_decode_ts();
01505
01506 if (0)
01507 init_jpeg_context();
01508
01509
01510 egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
01511 if (egl_display == EGL_NO_DISPLAY)
01512 {
01513 cout<<"Error while get EGL display connection"<<endl;
01514 return -1;
01515 }
01516
01517
01518 if (!eglInitialize(egl_display, NULL, NULL))
01519 {
01520 cout<<"Erro while initialize EGL display connection"<<endl;
01521 return -1;
01522 }
01523
01524 for (iterator = 0; iterator < cfg.channel_num; iterator++)
01525 {
01526 int ret = 0;
01527 sem_init(&(ctx[iterator].dec_run_sem), 0, 0);
01528 #ifdef ENABLE_GIE
01529 sem_init(&(ctx[iterator].result_ready_sem), 0, 0);
01530 #endif
01531 set_defaults(&ctx[iterator]);
01532
01533 char decname[512];
01534 sprintf(decname, "dec%d", iterator);
01535 ctx[iterator].channel = iterator;
01536
01537 if (parse_csv_args(&ctx[iterator],
01538 #ifdef ENABLE_GIE
01539 &g_gie_context,
01540 #endif
01541 argc - cfg.channel_num - 1, argp))
01542 {
01543 fprintf(stderr, "Error parsing commandline arguments\n");
01544 return -1;
01545 }
01546 ctx[iterator].in_file_path = cfg.in_file_path[iterator];
01547 ctx[iterator].nvosd_context = nvosd_create_context();
01548 ctx[iterator].dec = NvVideoDecoder::createVideoDecoder(decname);
01549 TEST_ERROR(!ctx[iterator].dec, "Could not create decoder", cleanup);
01550
01551
01552 ret = ctx[iterator].dec->subscribeEvent(V4L2_EVENT_RESOLUTION_CHANGE,
01553 0, 0);
01554 TEST_ERROR(ret < 0,
01555 "Could not subscribe to V4L2_EVENT_RESOLUTION_CHANGE",
01556 cleanup);
01557
01558
01559
01560
01561
01562 ret = ctx[iterator].dec->disableCompleteFrameInputBuffer();
01563 TEST_ERROR(ret < 0, "Error in disableCompleteFrameInputBuffer", cleanup);
01564
01565
01566 ret = ctx[iterator].dec->setOutputPlaneFormat(
01567 ctx[iterator].decoder_pixfmt, CHUNK_SIZE);
01568 TEST_ERROR(ret < 0, "Could not set output plane format", cleanup);
01569
01570
01571
01572 if (ctx[iterator].disable_dpb)
01573 {
01574 ret = ctx[iterator].dec->disableDPB();
01575 TEST_ERROR(ret < 0, "Error in disableDPB", cleanup);
01576 }
01577
01578
01579
01580 ret = ctx[iterator].dec->output_plane.setupPlane(
01581 V4L2_MEMORY_MMAP, 10, true, false);
01582 TEST_ERROR(ret < 0, "Error while setting up output plane", cleanup);
01583
01584 ctx[iterator].in_file = new ifstream(ctx[iterator].in_file_path);
01585 TEST_ERROR(!ctx[iterator].in_file->is_open(),
01586 "Error opening input file", cleanup);
01587
01588 if (ctx[iterator].out_file_path)
01589 {
01590 ctx[iterator].out_file = new ofstream(ctx[iterator].out_file_path);
01591 TEST_ERROR(!ctx[iterator].out_file->is_open(),
01592 "Error opening output file",
01593 cleanup);
01594 }
01595
01596 pthread_create(&ctx[iterator].render_feed_handle, NULL,
01597 render_thread, &ctx[iterator]);
01598
01599
01600 char convname[512];
01601 sprintf(convname, "conv%d", iterator);
01602 ctx[iterator].conv = NvVideoConverter::createVideoConverter(convname);
01603 TEST_ERROR(!ctx[iterator].conv, "Could not create video converter",
01604 cleanup);
01605
01606 ctx[iterator].conv->output_plane.
01607 setDQThreadCallback(conv_output_dqbuf_thread_callback);
01608 ctx[iterator].conv->capture_plane.
01609 setDQThreadCallback(conv_capture_dqbuf_thread_callback);
01610 #ifdef ENABLE_GIE
01611 if (iterator < g_gie_context.getNumGieInstances())
01612 {
01613 sprintf(convname, "conv1-%d", iterator);
01614 ctx[iterator].conv1 =
01615 NvVideoConverter::createVideoConverter(convname);
01616 TEST_ERROR(!ctx[iterator].conv1, "Could not create video converter",
01617 cleanup);
01618
01619 ctx[iterator].conv1->output_plane.
01620 setDQThreadCallback(conv1_output_dqbuf_thread_callback);
01621 ctx[iterator].conv1->capture_plane.
01622 setDQThreadCallback(conv1_capture_dqbuf_thread_callback);
01623 }
01624 #endif
01625 ret = ctx[iterator].dec->output_plane.setStreamStatus(true);
01626 TEST_ERROR(ret < 0, "Error in output plane stream on", cleanup);
01627 if (cfg.channel_num == 1)
01628 {
01629 ctx[iterator].window_width = disp_info.window_width;
01630 ctx[iterator].window_height = disp_info.window_height;
01631 ctx[iterator].window_x = 0;
01632 ctx[iterator].window_y = 0;
01633 }
01634 else
01635 {
01636 if (iterator == 0)
01637 {
01638 ctx[iterator].window_width = disp_info.window_width / 2;
01639 ctx[iterator].window_height = disp_info.window_height / 2;
01640 ctx[iterator].window_x = 0;
01641 ctx[iterator].window_y = 0;
01642 }
01643 else if (iterator == 1)
01644 {
01645 ctx[iterator].window_width = disp_info.window_width / 2;
01646 ctx[iterator].window_height = disp_info.window_height / 2;
01647 ctx[iterator].window_x = disp_info.window_width / 2;
01648 ctx[iterator].window_y = 0;
01649 }
01650 else if (iterator == 2)
01651 {
01652 ctx[iterator].window_width = disp_info.window_width / 2;
01653 ctx[iterator].window_height = disp_info.window_height / 2;
01654 ctx[iterator].window_x = 0;
01655 ctx[iterator].window_y = disp_info.window_height / 2;
01656 }
01657 else
01658 {
01659 ctx[iterator].window_width = disp_info.window_width / 2;
01660 ctx[iterator].window_height = disp_info.window_height / 2;
01661 ctx[iterator].window_x = disp_info.window_width / 2;
01662 ctx[iterator].window_y = disp_info.window_height / 2;
01663 }
01664 }
01665 if (ctx[iterator].cpu_occupation_option != PARSER)
01666 pthread_create(&ctx[iterator].dec_capture_loop, NULL,
01667 dec_capture_loop_fcn, &ctx[iterator]);
01668 pthread_create(&ctx[iterator].dec_feed_handle, NULL,
01669 dec_feed_loop_fcn, &ctx[iterator]);
01670 }
01671
01672 cleanup:
01673 for (iterator = 0; iterator < cfg.channel_num; iterator++)
01674 {
01675 sem_wait(&(ctx[iterator].dec_run_sem));
01676
01677
01678 ctx[iterator].stop_render = 1;
01679 pthread_cond_broadcast(&ctx[iterator].render_cond);
01680 pthread_join(ctx[iterator].render_feed_handle, NULL);
01681 #ifdef ENABLE_GIE
01682 if (GIE_Stop == 0)
01683 {
01684 GIE_Stop = 1;
01685 pthread_cond_broadcast(&GIE_cond);
01686 pthread_join(GIE_Thread_handle, NULL);
01687 }
01688 #endif
01689 ctx[iterator].conv->waitForIdle(-1);
01690 ctx[iterator].conv->capture_plane.stopDQThread();
01691 ctx[iterator].conv->output_plane.stopDQThread();
01692 #ifdef ENABLE_GIE
01693 if (iterator < g_gie_context.getNumGieInstances())
01694 {
01695 ctx[iterator].conv1->waitForIdle(-1);
01696 ctx[iterator].conv1->capture_plane.stopDQThread();
01697 ctx[iterator].conv1->output_plane.stopDQThread();
01698 }
01699 #endif
01700 pthread_join(ctx[iterator].dec_feed_handle, NULL);
01701 if (ctx[iterator].cpu_occupation_option != PARSER)
01702 pthread_join(ctx[iterator].dec_capture_loop, NULL);
01703
01704 if (ctx[iterator].dec->isInError())
01705 {
01706 cerr << "Decoder is in error" << endl;
01707 error = 1;
01708 }
01709
01710 if (ctx[iterator].got_error)
01711 {
01712 error = 1;
01713 }
01714
01715 if (ctx[iterator].do_stat)
01716 do_statistic(&ctx[iterator]);
01717
01718 sem_destroy(&(ctx[iterator].dec_run_sem));
01719 #ifdef ENABLE_GIE
01720 sem_destroy(&(ctx[iterator].result_ready_sem));
01721 pthread_mutex_destroy(&ctx[iterator].osd_lock);
01722 #endif
01723
01724
01725
01726 delete ctx[iterator].dec;
01727
01728
01729 if (ctx->cpu_occupation_option == PARSER_DECODER_VIC_RENDER)
01730 delete ctx[iterator].renderer;
01731 delete ctx[iterator].in_file;
01732 delete ctx[iterator].out_file;
01733 delete ctx[iterator].conv_output_plane_buf_queue;
01734 delete ctx[iterator].render_buf_queue;
01735 if (!ctx[iterator].nvosd_context)
01736 {
01737 nvosd_destroy_context(ctx[iterator].nvosd_context);
01738 ctx[iterator].nvosd_context = NULL;
01739 }
01740 #ifdef ENABLE_GIE
01741 delete ctx[iterator].osd_queue;
01742 if (iterator < g_gie_context.getNumGieInstances())
01743 {
01744 delete ctx[iterator].conv1_output_plane_buf_queue;
01745 }
01746 #endif
01747
01748 if (ctx[iterator].do_stat)
01749 {
01750 for( iter = ctx[iterator].frame_info_map->begin();
01751 iter != ctx[iterator].frame_info_map->end(); iter++)
01752 {
01753 delete iter->second;
01754 }
01755 }
01756 delete ctx[iterator].frame_info_map;
01757
01758 if (error)
01759 {
01760 cout << "App run failed" << endl;
01761 }
01762 else
01763 {
01764 cout << "App run was successful" << endl;
01765 }
01766 }
01767 #ifdef ENABLE_GIE
01768 #if USE_CPU_FOR_INTFLOAT_CONVERSION
01769 g_gie_context.destroyGieContext(true);
01770 #else
01771 g_gie_context.destroyGieContext();
01772 #endif
01773 #endif
01774
01775 if (egl_display)
01776 {
01777 if (!eglTerminate(egl_display))
01778 {
01779 cout<<"Error while terminate EGL display connection";
01780 return -1;
01781 }
01782 }
01783
01784 if (0)
01785 destroy_jpeg_context();
01786
01787 return -error;
01788 }