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 "NvApplicationProfiler.h"
00030 #include "NvUtils.h"
00031 #include <errno.h>
00032 #include <fstream>
00033 #include <iostream>
00034 #include <linux/videodev2.h>
00035 #include <malloc.h>
00036 #include <pthread.h>
00037 #include <string.h>
00038 #include <unistd.h>
00039
00040 #include "video_decode.h"
00041
00042 #define TEST_ERROR(cond, str, label) if(cond) { \
00043 cerr << str << endl; \
00044 error = 1; \
00045 goto label; }
00046
00047 #define CHUNK_SIZE 4000000
00048 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
00049
00050 #define IS_NAL_UNIT_START(buffer_ptr) (!buffer_ptr[0] && !buffer_ptr[1] && \
00051 !buffer_ptr[2] && (buffer_ptr[3] == 1))
00052
00053 #define IS_NAL_UNIT_START1(buffer_ptr) (!buffer_ptr[0] && !buffer_ptr[1] && \
00054 (buffer_ptr[2] == 1))
00055
00056 using namespace std;
00057
00058 static int
00059 read_decoder_input_nalu(ifstream * stream, NvBuffer * buffer,
00060 char *parse_buffer, streamsize parse_buffer_size)
00061 {
00062
00063 char *buffer_ptr = (char *) buffer->planes[0].data;
00064
00065 char *stream_ptr;
00066 bool nalu_found = false;
00067
00068 streamsize bytes_read;
00069 streamsize stream_initial_pos = stream->tellg();
00070
00071 stream->read(parse_buffer, parse_buffer_size);
00072 bytes_read = stream->gcount();
00073
00074 if (bytes_read == 0)
00075 {
00076 return buffer->planes[0].bytesused = 0;
00077 }
00078
00079
00080 stream_ptr = parse_buffer;
00081 while ((stream_ptr - parse_buffer) < (bytes_read - 3))
00082 {
00083 nalu_found = IS_NAL_UNIT_START(stream_ptr) ||
00084 IS_NAL_UNIT_START1(stream_ptr);
00085 if (nalu_found)
00086 {
00087 break;
00088 }
00089 stream_ptr++;
00090 }
00091
00092
00093 if (!nalu_found)
00094 {
00095 cerr << "Could not read nal unit from file. File seems to be corrupted"
00096 << endl;
00097 return -1;
00098 }
00099
00100 memcpy(buffer_ptr, stream_ptr, 4);
00101 buffer_ptr += 4;
00102 buffer->planes[0].bytesused = 4;
00103 stream_ptr += 4;
00104
00105
00106 while ((stream_ptr - parse_buffer) < (bytes_read - 3))
00107 {
00108 if (IS_NAL_UNIT_START(stream_ptr) || IS_NAL_UNIT_START1(stream_ptr))
00109 {
00110 streamsize seekto = stream_initial_pos +
00111 (stream_ptr - parse_buffer);
00112 if(stream->eof())
00113 {
00114 stream->clear();
00115 }
00116 stream->seekg(seekto, stream->beg);
00117 return 0;
00118 }
00119 *buffer_ptr = *stream_ptr;
00120 buffer_ptr++;
00121 stream_ptr++;
00122 buffer->planes[0].bytesused++;
00123 }
00124
00125
00126 cerr << "Could not read nal unit from file. File seems to be corrupted"
00127 << endl;
00128 return -1;
00129 }
00130
00131 static int
00132 read_decoder_input_chunk(ifstream * stream, NvBuffer * buffer)
00133 {
00134
00135 streamsize bytes_to_read = MIN(CHUNK_SIZE, buffer->planes[0].length);
00136
00137 stream->read((char *) buffer->planes[0].data, bytes_to_read);
00138
00139
00140 buffer->planes[0].bytesused = stream->gcount();
00141 return 0;
00142 }
00143
00144 static void
00145 abort(context_t *ctx)
00146 {
00147 ctx->got_error = true;
00148 ctx->dec->abort();
00149 if (ctx->conv)
00150 {
00151 ctx->conv->abort();
00152 pthread_cond_broadcast(&ctx->queue_cond);
00153 }
00154 }
00155
00156 static bool
00157 conv0_output_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
00158 NvBuffer * buffer, NvBuffer * shared_buffer,
00159 void *arg)
00160 {
00161 context_t *ctx = (context_t *) arg;
00162 struct v4l2_buffer dec_capture_ret_buffer;
00163 struct v4l2_plane planes[MAX_PLANES];
00164
00165 if (!v4l2_buf)
00166 {
00167 cerr << "Error while dequeueing conv output plane buffer" << endl;
00168 abort(ctx);
00169 return false;
00170 }
00171
00172 if (v4l2_buf->m.planes[0].bytesused == 0)
00173 {
00174 return false;
00175 }
00176
00177 memset(&dec_capture_ret_buffer, 0, sizeof(dec_capture_ret_buffer));
00178 memset(planes, 0, sizeof(planes));
00179
00180 dec_capture_ret_buffer.index = shared_buffer->index;
00181 dec_capture_ret_buffer.m.planes = planes;
00182
00183 pthread_mutex_lock(&ctx->queue_lock);
00184 ctx->conv_output_plane_buf_queue->push(buffer);
00185
00186
00187
00188 if (ctx->dec->capture_plane.qBuffer(dec_capture_ret_buffer, NULL) < 0)
00189 {
00190 abort(ctx);
00191 return false;
00192 }
00193
00194 pthread_cond_broadcast(&ctx->queue_cond);
00195 pthread_mutex_unlock(&ctx->queue_lock);
00196
00197 return true;
00198 }
00199
00200 static bool
00201 conv0_capture_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
00202 NvBuffer * buffer, NvBuffer * shared_buffer,
00203 void *arg)
00204 {
00205 context_t *ctx = (context_t *) arg;
00206
00207 if (!v4l2_buf)
00208 {
00209 cerr << "Error while dequeueing conv capture plane buffer" << endl;
00210 abort(ctx);
00211 return false;
00212 }
00213
00214 if (v4l2_buf->m.planes[0].bytesused == 0)
00215 {
00216 return false;
00217 }
00218
00219
00220
00221 if (!ctx->stats && ctx->out_file)
00222 {
00223 write_video_frame(ctx->out_file, *buffer);
00224 }
00225
00226 if (!ctx->stats && !ctx->disable_rendering)
00227 {
00228 ctx->renderer->render(buffer->planes[0].fd);
00229 }
00230
00231 if (ctx->conv->capture_plane.qBuffer(*v4l2_buf, NULL) < 0)
00232 {
00233 return false;
00234 }
00235 return true;
00236 }
00237
00238 static void
00239 report_metadata(context_t *ctx, v4l2_ctrl_videodec_outputbuf_metadata *metadata)
00240 {
00241 uint32_t frame_num = ctx->dec->capture_plane.getTotalDequeuedBuffers() - 1;
00242
00243 cout << "Frame " << frame_num << endl;
00244
00245 if (metadata->bValidFrameStatus)
00246 {
00247 if (ctx->decoder_pixfmt == V4L2_PIX_FMT_H264)
00248 {
00249 switch(metadata->CodecParams.H264DecParams.FrameType)
00250 {
00251 case 0:
00252 cout << "FrameType = B" << endl;
00253 break;
00254 case 1:
00255 cout << "FrameType = P" << endl;
00256 break;
00257 case 2:
00258 cout << "FrameType = I";
00259 if (metadata->CodecParams.H264DecParams.dpbInfo.currentFrame.bIdrFrame)
00260 {
00261 cout << " (IDR)";
00262 }
00263 cout << endl;
00264 break;
00265 }
00266 }
00267
00268 if (ctx->decoder_pixfmt == V4L2_PIX_FMT_H265)
00269 {
00270 switch(metadata->CodecParams.HEVCDecParams.FrameType)
00271 {
00272 case 0:
00273 cout << "FrameType = B" << endl;
00274 break;
00275 case 1:
00276 cout << "FrameType = P" << endl;
00277 break;
00278 case 2:
00279 cout << "FrameType = I";
00280 if (metadata->CodecParams.HEVCDecParams.dpbInfo.currentFrame.bIdrFrame)
00281 {
00282 cout << " (IDR)";
00283 }
00284 cout << endl;
00285 break;
00286 }
00287 }
00288
00289 if (metadata->FrameDecStats.DecodeError)
00290 {
00291 v4l2_ctrl_videodec_statusmetadata *dec_stats =
00292 &metadata->FrameDecStats;
00293 cout << "ErrorType=" << dec_stats->DecodeError << " Decoded MBs=" <<
00294 dec_stats->DecodedMBs << " Concealed MBs=" <<
00295 dec_stats->ConcealedMBs << endl;
00296 }
00297 }
00298 else
00299 {
00300 cout << "No valid metadata for frame" << endl;
00301 }
00302 }
00303
00304 static int
00305 sendEOStoConverter(context_t *ctx)
00306 {
00307
00308 if (ctx->conv->output_plane.getStreamStatus())
00309 {
00310 NvBuffer *conv_buffer;
00311 struct v4l2_buffer v4l2_buf;
00312 struct v4l2_plane planes[MAX_PLANES];
00313
00314 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00315 memset(&planes, 0, sizeof(planes));
00316
00317 v4l2_buf.m.planes = planes;
00318 pthread_mutex_lock(&ctx->queue_lock);
00319 while (ctx->conv_output_plane_buf_queue->empty())
00320 {
00321 pthread_cond_wait(&ctx->queue_cond, &ctx->queue_lock);
00322 }
00323 conv_buffer = ctx->conv_output_plane_buf_queue->front();
00324 ctx->conv_output_plane_buf_queue->pop();
00325 pthread_mutex_unlock(&ctx->queue_lock);
00326
00327 v4l2_buf.index = conv_buffer->index;
00328
00329
00330 return ctx->conv->output_plane.qBuffer(v4l2_buf, NULL);
00331 }
00332 return 0;
00333 }
00334
00335 static void
00336 query_and_set_capture(context_t * ctx)
00337 {
00338 NvVideoDecoder *dec = ctx->dec;
00339 struct v4l2_format format;
00340 struct v4l2_crop crop;
00341 int32_t min_dec_capture_buffers;
00342 int ret = 0;
00343 int error = 0;
00344 uint32_t window_width;
00345 uint32_t window_height;
00346
00347
00348
00349 ret = dec->capture_plane.getFormat(format);
00350 TEST_ERROR(ret < 0,
00351 "Error: Could not get format from decoder capture plane", error);
00352
00353
00354 ret = dec->capture_plane.getCrop(crop);
00355 TEST_ERROR(ret < 0,
00356 "Error: Could not get crop from decoder capture plane", error);
00357
00358 cout << "Video Resolution: " << crop.c.width << "x" << crop.c.height
00359 << endl;
00360
00361
00362
00363
00364 if (ctx->conv)
00365 {
00366 ret = sendEOStoConverter(ctx);
00367 TEST_ERROR(ret < 0,
00368 "Error while queueing EOS buffer on converter output",
00369 error);
00370
00371 ctx->conv->capture_plane.waitForDQThread(2000);
00372
00373 ctx->conv->output_plane.deinitPlane();
00374 ctx->conv->capture_plane.deinitPlane();
00375
00376 while(!ctx->conv_output_plane_buf_queue->empty())
00377 {
00378 ctx->conv_output_plane_buf_queue->pop();
00379 }
00380 }
00381
00382 if (!ctx->disable_rendering)
00383 {
00384
00385 delete ctx->renderer;
00386
00387 if (ctx->fullscreen)
00388 {
00389
00390 window_width = window_height = 0;
00391 }
00392 else if (ctx->window_width && ctx->window_height)
00393 {
00394
00395 window_width = ctx->window_width;
00396 window_height = ctx->window_height;
00397 }
00398 else
00399 {
00400
00401 window_width = crop.c.width;
00402 window_height = crop.c.height;
00403 }
00404
00405
00406
00407 ctx->renderer =
00408 NvEglRenderer::createEglRenderer("renderer0", window_width,
00409 window_height, ctx->window_x,
00410 ctx->window_y);
00411 TEST_ERROR(!ctx->renderer,
00412 "Error in setting up renderer. "
00413 "Check if X is running or run with --disable-rendering",
00414 error);
00415 if (ctx->stats)
00416 {
00417 ctx->renderer->enableProfiling();
00418 }
00419
00420 ctx->renderer->setFPS(ctx->fps);
00421 }
00422
00423
00424 dec->capture_plane.deinitPlane();
00425
00426
00427
00428 ret = dec->setCapturePlaneFormat(format.fmt.pix_mp.pixelformat,
00429 format.fmt.pix_mp.width,
00430 format.fmt.pix_mp.height);
00431 TEST_ERROR(ret < 0, "Error in setting decoder capture plane format", error);
00432
00433
00434 ret = dec->getMinimumCapturePlaneBuffers(min_dec_capture_buffers);
00435 TEST_ERROR(ret < 0,
00436 "Error while getting value of minimum capture plane buffers",
00437 error);
00438
00439
00440 ret =
00441 dec->capture_plane.setupPlane(V4L2_MEMORY_MMAP,
00442 min_dec_capture_buffers + 5, false,
00443 false);
00444 TEST_ERROR(ret < 0, "Error in decoder capture plane setup", error);
00445
00446 if (ctx->conv)
00447 {
00448 ret = ctx->conv->setOutputPlaneFormat(format.fmt.pix_mp.pixelformat,
00449 format.fmt.pix_mp.width,
00450 format.fmt.pix_mp.height,
00451 V4L2_NV_BUFFER_LAYOUT_BLOCKLINEAR);
00452 TEST_ERROR(ret < 0, "Error in converter output plane set format",
00453 error);
00454
00455 ret = ctx->conv->setCapturePlaneFormat((ctx->out_pixfmt == 1 ?
00456 V4L2_PIX_FMT_NV12M :
00457 V4L2_PIX_FMT_YUV420M),
00458 crop.c.width,
00459 crop.c.height,
00460 V4L2_NV_BUFFER_LAYOUT_PITCH);
00461 TEST_ERROR(ret < 0, "Error in converter capture plane set format",
00462 error);
00463
00464 ret = ctx->conv->setCropRect(0, 0, crop.c.width, crop.c.height);
00465 TEST_ERROR(ret < 0, "Error while setting crop rect", error);
00466
00467 ret =
00468 ctx->conv->output_plane.setupPlane(V4L2_MEMORY_DMABUF,
00469 dec->capture_plane.
00470 getNumBuffers(), false, false);
00471 TEST_ERROR(ret < 0, "Error in converter output plane setup", error);
00472
00473 ret =
00474 ctx->conv->capture_plane.setupPlane(V4L2_MEMORY_MMAP,
00475 dec->capture_plane.
00476 getNumBuffers(), true, false);
00477 TEST_ERROR(ret < 0, "Error in converter capture plane setup", error);
00478
00479 ret = ctx->conv->output_plane.setStreamStatus(true);
00480 TEST_ERROR(ret < 0, "Error in converter output plane streamon", error);
00481
00482 ret = ctx->conv->capture_plane.setStreamStatus(true);
00483 TEST_ERROR(ret < 0, "Error in converter output plane streamoff", error);
00484
00485
00486 for (uint32_t i = 0; i < ctx->conv->output_plane.getNumBuffers(); i++)
00487 {
00488 ctx->conv_output_plane_buf_queue->push(ctx->conv->output_plane.
00489 getNthBuffer(i));
00490 }
00491
00492 for (uint32_t i = 0; i < ctx->conv->capture_plane.getNumBuffers(); i++)
00493 {
00494 struct v4l2_buffer v4l2_buf;
00495 struct v4l2_plane planes[MAX_PLANES];
00496
00497 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00498 memset(planes, 0, sizeof(planes));
00499
00500 v4l2_buf.index = i;
00501 v4l2_buf.m.planes = planes;
00502 ret = ctx->conv->capture_plane.qBuffer(v4l2_buf, NULL);
00503 TEST_ERROR(ret < 0, "Error Qing buffer at converter capture plane",
00504 error);
00505 }
00506 ctx->conv->output_plane.startDQThread(ctx);
00507 ctx->conv->capture_plane.startDQThread(ctx);
00508
00509 }
00510
00511
00512 ret = dec->capture_plane.setStreamStatus(true);
00513 TEST_ERROR(ret < 0, "Error in decoder capture plane streamon", error);
00514
00515
00516 for (uint32_t i = 0; i < dec->capture_plane.getNumBuffers(); i++)
00517 {
00518 struct v4l2_buffer v4l2_buf;
00519 struct v4l2_plane planes[MAX_PLANES];
00520
00521 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00522 memset(planes, 0, sizeof(planes));
00523
00524 v4l2_buf.index = i;
00525 v4l2_buf.m.planes = planes;
00526 ret = dec->capture_plane.qBuffer(v4l2_buf, NULL);
00527 TEST_ERROR(ret < 0, "Error Qing buffer at output plane", error);
00528 }
00529 cout << "Query and set capture successful" << endl;
00530 return;
00531
00532 error:
00533 if (error)
00534 {
00535 abort(ctx);
00536 cerr << "Error in " << __func__ << endl;
00537 }
00538 }
00539
00540 static void *
00541 dec_capture_loop_fcn(void *arg)
00542 {
00543 context_t *ctx = (context_t *) arg;
00544 NvVideoDecoder *dec = ctx->dec;
00545 struct v4l2_event ev;
00546 int ret;
00547
00548 cout << "Starting decoder capture loop thread" << endl;
00549
00550
00551
00552 do
00553 {
00554 ret = dec->dqEvent(ev, 50000);
00555 if (ret < 0)
00556 {
00557 if (errno == EAGAIN)
00558 {
00559 cerr <<
00560 "Timed out waiting for first V4L2_EVENT_RESOLUTION_CHANGE"
00561 << endl;
00562 }
00563 else
00564 {
00565 cerr << "Error in dequeueing decoder event" << endl;
00566 }
00567 abort(ctx);
00568 break;
00569 }
00570 }
00571 while (ev.type != V4L2_EVENT_RESOLUTION_CHANGE);
00572
00573
00574 if (!ctx->got_error)
00575 query_and_set_capture(ctx);
00576
00577
00578 while (!(ctx->got_error || dec->isInError() || ctx->got_eos))
00579 {
00580 NvBuffer *dec_buffer;
00581
00582
00583 ret = dec->dqEvent(ev, false);
00584 if (ret == 0)
00585 {
00586 switch (ev.type)
00587 {
00588 case V4L2_EVENT_RESOLUTION_CHANGE:
00589 query_and_set_capture(ctx);
00590 continue;
00591 }
00592 }
00593
00594 while (1)
00595 {
00596 struct v4l2_buffer v4l2_buf;
00597 struct v4l2_plane planes[MAX_PLANES];
00598
00599 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00600 memset(planes, 0, sizeof(planes));
00601 v4l2_buf.m.planes = planes;
00602
00603
00604 if (dec->capture_plane.dqBuffer(v4l2_buf, &dec_buffer, NULL, 0))
00605 {
00606 if (errno == EAGAIN)
00607 {
00608 usleep(1000);
00609 }
00610 else
00611 {
00612 abort(ctx);
00613 cerr << "Error while calling dequeue at capture plane" <<
00614 endl;
00615 }
00616 break;
00617 }
00618
00619 if (ctx->enable_metadata)
00620 {
00621 v4l2_ctrl_videodec_outputbuf_metadata dec_metadata;
00622
00623 ret = dec->getMetadata(v4l2_buf.index, dec_metadata);
00624 if (ret == 0)
00625 {
00626 report_metadata(ctx, &dec_metadata);
00627 }
00628 }
00629
00630 if (!ctx->disable_rendering && ctx->stats)
00631 {
00632
00633 ctx->renderer->render(dec_buffer->planes[0].fd);
00634 }
00635
00636
00637
00638
00639 if (ctx->out_file || (!ctx->disable_rendering && !ctx->stats))
00640 {
00641 NvBuffer *conv_buffer;
00642 struct v4l2_buffer conv_output_buffer;
00643 struct v4l2_plane conv_planes[MAX_PLANES];
00644
00645 memset(&conv_output_buffer, 0, sizeof(conv_output_buffer));
00646 memset(conv_planes, 0, sizeof(conv_planes));
00647 conv_output_buffer.m.planes = conv_planes;
00648
00649
00650 pthread_mutex_lock(&ctx->queue_lock);
00651 while (ctx->conv_output_plane_buf_queue->empty())
00652 {
00653 pthread_cond_wait(&ctx->queue_cond, &ctx->queue_lock);
00654 }
00655 conv_buffer = ctx->conv_output_plane_buf_queue->front();
00656 ctx->conv_output_plane_buf_queue->pop();
00657 pthread_mutex_unlock(&ctx->queue_lock);
00658
00659 conv_output_buffer.index = conv_buffer->index;
00660
00661 if (ctx->conv->output_plane.
00662 qBuffer(conv_output_buffer, dec_buffer) < 0)
00663 {
00664 abort(ctx);
00665 cerr <<
00666 "Error while queueing buffer at converter output plane"
00667 << endl;
00668 break;
00669 }
00670 }
00671 else
00672 {
00673
00674
00675 if (dec->capture_plane.qBuffer(v4l2_buf, NULL) < 0)
00676 {
00677 abort(ctx);
00678 cerr <<
00679 "Error while queueing buffer at decoder capture plane"
00680 << endl;
00681 break;
00682 }
00683 }
00684 }
00685 }
00686
00687 if (ctx->conv)
00688 {
00689 if (sendEOStoConverter(ctx) < 0)
00690 {
00691 cerr << "Error while queueing EOS buffer on converter output"
00692 << endl;
00693 }
00694 }
00695 cout << "Exiting decoder capture loop thread" << endl;
00696 return NULL;
00697 }
00698
00699 static void
00700 set_defaults(context_t * ctx)
00701 {
00702 memset(ctx, 0, sizeof(context_t));
00703 ctx->fullscreen = false;
00704 ctx->window_height = 0;
00705 ctx->window_width = 0;
00706 ctx->window_x = 0;
00707 ctx->window_y = 0;
00708 ctx->out_pixfmt = 1;
00709 ctx->fps = 30;
00710
00711 ctx->conv_output_plane_buf_queue = new queue < NvBuffer * >;
00712 pthread_mutex_init(&ctx->queue_lock, NULL);
00713 pthread_cond_init(&ctx->queue_cond, NULL);
00714 }
00715
00716 int
00717 main(int argc, char *argv[])
00718 {
00719 context_t ctx;
00720 int ret = 0;
00721 int error = 0;
00722 uint32_t i;
00723 bool eos = false;
00724 char *nalu_parse_buffer = NULL;
00725 NvApplicationProfiler &profiler = NvApplicationProfiler::getProfilerInstance();
00726
00727 set_defaults(&ctx);
00728
00729 if (parse_csv_args(&ctx, argc, argv))
00730 {
00731 fprintf(stderr, "Error parsing commandline arguments\n");
00732 return -1;
00733 }
00734
00735 ctx.dec = NvVideoDecoder::createVideoDecoder("dec0");
00736 TEST_ERROR(!ctx.dec, "Could not create decoder", cleanup);
00737
00738 if (ctx.stats)
00739 {
00740 profiler.start(NvApplicationProfiler::DefaultSamplingInterval);
00741 ctx.dec->enableProfiling();
00742 }
00743
00744
00745 ret = ctx.dec->subscribeEvent(V4L2_EVENT_RESOLUTION_CHANGE, 0, 0);
00746 TEST_ERROR(ret < 0, "Could not subscribe to V4L2_EVENT_RESOLUTION_CHANGE",
00747 cleanup);
00748
00749 if (ctx.input_nalu)
00750 {
00751 nalu_parse_buffer = new char[CHUNK_SIZE];
00752 }
00753 else
00754 {
00755
00756
00757
00758
00759 ret = ctx.dec->disableCompleteFrameInputBuffer();
00760 TEST_ERROR(ret < 0,
00761 "Error in decoder disableCompleteFrameInputBuffer", cleanup);
00762 }
00763
00764
00765 ret = ctx.dec->setOutputPlaneFormat(ctx.decoder_pixfmt, CHUNK_SIZE);
00766 TEST_ERROR(ret < 0, "Could not set output plane format", cleanup);
00767
00768
00769
00770 if (ctx.disable_dpb)
00771 {
00772 ret = ctx.dec->disableDPB();
00773 TEST_ERROR(ret < 0, "Error in decoder disableDPB", cleanup);
00774 }
00775
00776 if (ctx.enable_metadata)
00777 {
00778 ret = ctx.dec->enableMetadataReporting();
00779 TEST_ERROR(ret < 0, "Error while enabling metadata reporting", cleanup);
00780 }
00781
00782 if (ctx.skip_frames)
00783 {
00784 ret = ctx.dec->setSkipFrames(ctx.skip_frames);
00785 TEST_ERROR(ret < 0, "Error while setting skip frames param", cleanup);
00786 }
00787
00788
00789
00790 ret = ctx.dec->output_plane.setupPlane(V4L2_MEMORY_MMAP, 10, true, false);
00791 TEST_ERROR(ret < 0, "Error while setting up output plane", cleanup);
00792
00793 ctx.in_file = new ifstream(ctx.in_file_path);
00794 TEST_ERROR(!ctx.in_file->is_open(), "Error opening input file", cleanup);
00795
00796 if (ctx.out_file_path)
00797 {
00798 ctx.out_file = new ofstream(ctx.out_file_path);
00799 TEST_ERROR(!ctx.out_file->is_open(), "Error opening output file",
00800 cleanup);
00801 }
00802
00803 if (ctx.out_file || (!ctx.disable_rendering && !ctx.stats))
00804 {
00805
00806
00807 ctx.conv = NvVideoConverter::createVideoConverter("conv0");
00808 TEST_ERROR(!ctx.conv, "Could not create video converter", cleanup);
00809 ctx.conv->output_plane.
00810 setDQThreadCallback(conv0_output_dqbuf_thread_callback);
00811 ctx.conv->capture_plane.
00812 setDQThreadCallback(conv0_capture_dqbuf_thread_callback);
00813
00814 if (ctx.stats)
00815 {
00816 ctx.conv->enableProfiling();
00817 }
00818 }
00819
00820 ret = ctx.dec->output_plane.setStreamStatus(true);
00821 TEST_ERROR(ret < 0, "Error in output plane stream on", cleanup);
00822
00823 pthread_create(&ctx.dec_capture_loop, NULL, dec_capture_loop_fcn, &ctx);
00824
00825
00826
00827 i = 0;
00828 while (!eos && !ctx.got_error && !ctx.dec->isInError() &&
00829 i < ctx.dec->output_plane.getNumBuffers())
00830 {
00831 struct v4l2_buffer v4l2_buf;
00832 struct v4l2_plane planes[MAX_PLANES];
00833 NvBuffer *buffer;
00834
00835 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00836 memset(planes, 0, sizeof(planes));
00837
00838 buffer = ctx.dec->output_plane.getNthBuffer(i);
00839 if (ctx.input_nalu)
00840 {
00841 read_decoder_input_nalu(ctx.in_file, buffer, nalu_parse_buffer,
00842 CHUNK_SIZE);
00843 }
00844 else
00845 {
00846 read_decoder_input_chunk(ctx.in_file, buffer);
00847 }
00848
00849 v4l2_buf.index = i;
00850 v4l2_buf.m.planes = planes;
00851 v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;
00852
00853
00854
00855 ret = ctx.dec->output_plane.qBuffer(v4l2_buf, NULL);
00856 if (ret < 0)
00857 {
00858 cerr << "Error Qing buffer at output plane" << endl;
00859 abort(&ctx);
00860 break;
00861 }
00862 if (v4l2_buf.m.planes[0].bytesused == 0)
00863 {
00864 eos = true;
00865 cout << "Input file read complete" << endl;
00866 break;
00867 }
00868 i++;
00869 }
00870
00871
00872
00873
00874 while (!eos && !ctx.got_error && !ctx.dec->isInError())
00875 {
00876 struct v4l2_buffer v4l2_buf;
00877 struct v4l2_plane planes[MAX_PLANES];
00878 NvBuffer *buffer;
00879
00880 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00881 memset(planes, 0, sizeof(planes));
00882
00883 v4l2_buf.m.planes = planes;
00884
00885 ret = ctx.dec->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, -1);
00886 if (ret < 0)
00887 {
00888 cerr << "Error DQing buffer at output plane" << endl;
00889 abort(&ctx);
00890 break;
00891 }
00892
00893 if (ctx.input_nalu)
00894 {
00895 read_decoder_input_nalu(ctx.in_file, buffer, nalu_parse_buffer,
00896 CHUNK_SIZE);
00897 }
00898 else
00899 {
00900 read_decoder_input_chunk(ctx.in_file, buffer);
00901 }
00902 v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;
00903 ret = ctx.dec->output_plane.qBuffer(v4l2_buf, NULL);
00904 if (ret < 0)
00905 {
00906 cerr << "Error Qing buffer at output plane" << endl;
00907 abort(&ctx);
00908 break;
00909 }
00910 if (v4l2_buf.m.planes[0].bytesused == 0)
00911 {
00912 eos = true;
00913 cout << "Input file read complete" << endl;
00914 break;
00915 }
00916 }
00917
00918
00919
00920 while (ctx.dec->output_plane.getNumQueuedBuffers() > 0 &&
00921 !ctx.got_error && !ctx.dec->isInError())
00922 {
00923 struct v4l2_buffer v4l2_buf;
00924 struct v4l2_plane planes[MAX_PLANES];
00925
00926 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
00927 memset(planes, 0, sizeof(planes));
00928
00929 v4l2_buf.m.planes = planes;
00930 ret = ctx.dec->output_plane.dqBuffer(v4l2_buf, NULL, NULL, -1);
00931 if (ret < 0)
00932 {
00933 cerr << "Error DQing buffer at output plane" << endl;
00934 abort(&ctx);
00935 break;
00936 }
00937 }
00938
00939
00940 ctx.got_eos = true;
00941
00942 if (ctx.conv)
00943 {
00944 ctx.conv->capture_plane.waitForDQThread(-1);
00945 }
00946
00947 if (ctx.stats)
00948 {
00949 profiler.stop();
00950 ctx.dec->printProfilingStats(cout);
00951 if (ctx.conv)
00952 {
00953 ctx.conv->printProfilingStats(cout);
00954 }
00955 if (ctx.renderer)
00956 {
00957 ctx.renderer->printProfilingStats(cout);
00958 }
00959 profiler.printProfilerData(cout);
00960 }
00961
00962 cleanup:
00963 if (ctx.dec_capture_loop)
00964 {
00965 pthread_join(ctx.dec_capture_loop, NULL);
00966 }
00967
00968 if (ctx.conv && ctx.conv->isInError())
00969 {
00970 cerr << "Converter is in error" << endl;
00971 error = 1;
00972 }
00973
00974 if (ctx.dec && ctx.dec->isInError())
00975 {
00976 cerr << "Decoder is in error" << endl;
00977 error = 1;
00978 }
00979
00980 if (ctx.got_error)
00981 {
00982 error = 1;
00983 }
00984
00985
00986
00987
00988 delete ctx.dec;
00989 delete ctx.conv;
00990
00991
00992 delete ctx.renderer;
00993 delete ctx.in_file;
00994 delete ctx.out_file;
00995 delete ctx.conv_output_plane_buf_queue;
00996 delete[] nalu_parse_buffer;
00997
00998 free(ctx.in_file_path);
00999 free(ctx.out_file_path);
01000
01001 if (error)
01002 {
01003 cout << "App run failed" << endl;
01004 }
01005 else
01006 {
01007 cout << "App run was successful" << endl;
01008 }
01009 return -error;
01010 }