void do_NAL (struct lib_cc_decode *ctx, unsigned char *NALstart, LLONG NAL_length, struct cc_subtitle *sub) { unsigned char *NALstop; enum ccx_avc_nal_types nal_unit_type = *NALstart & 0x1F; NALstop = NAL_length+NALstart; NALstop = remove_03emu(NALstart+1, NALstop); // Add +1 to NALstop for TS, without it for MP4. Still don't know why dvprint("BEGIN NAL unit type: %d length %d ref_idc: %d - Buffered captions before: %d\n", nal_unit_type, NALstop-NALstart-1, ctx->avc_ctx->nal_ref_idc, !ctx->avc_ctx->cc_buffer_saved); if (NALstop==NULL) // remove_03emu failed. { mprint ("\rNotice: NAL of type %u had to be skipped because remove_03emu failed.\n", nal_unit_type); return; } if ( nal_unit_type == CCX_NAL_TYPE_ACCESS_UNIT_DELIMITER_9 ) { // Found Access Unit Delimiter } else if ( nal_unit_type == CCX_NAL_TYPE_SEQUENCE_PARAMETER_SET_7 ) { // Found sequence parameter set // We need this to parse NAL type 1 (CCX_NAL_TYPE_CODED_SLICE_NON_IDR_PICTURE_1) ctx->avc_ctx->num_nal_unit_type_7++; seq_parameter_set_rbsp(ctx->avc_ctx, NALstart+1, NALstop); ctx->avc_ctx->got_seq_para = 1; } else if ( ctx->avc_ctx->got_seq_para && (nal_unit_type == CCX_NAL_TYPE_CODED_SLICE_NON_IDR_PICTURE_1 || nal_unit_type == CCX_NAL_TYPE_CODED_SLICE_IDR_PICTURE)) // Only if nal_unit_type=1 { // Found coded slice of a non-IDR picture // We only need the slice header data, no need to implement // slice_layer_without_partitioning_rbsp( ); slice_header(ctx, NALstart+1, NALstop, nal_unit_type, sub); } else if ( ctx->avc_ctx->got_seq_para && nal_unit_type == CCX_NAL_TYPE_SEI ) { // Found SEI (used for subtitles) //set_fts(ctx->timing); // FIXME - check this!!! sei_rbsp(ctx->avc_ctx, NALstart+1, NALstop); } else if ( ctx->avc_ctx->got_seq_para && nal_unit_type == CCX_NAL_TYPE_PICTURE_PARAMETER_SET ) { // Found Picture parameter set } if (temp_debug) { mprint ("NAL process failed.\n"); mprint ("\n After decoding, the actual thing was (length =%d)\n", NALstop-(NALstart+1)); dump (CCX_DMT_GENERIC_NOTICES,NALstart+1, NALstop-(NALstart+1),0, 0); } dvprint("END NAL unit type: %d length %d ref_idc: %d - Buffered captions after: %d\n", nal_unit_type, NALstop-NALstart-1, ctx->avc_ctx->nal_ref_idc, !ctx->avc_ctx->cc_buffer_saved); }
// Process SEI payload in AVC data. This function combines sei_rbsp() // and rbsp_trailing_bits(). void sei_rbsp (struct avc_ctx *ctx, unsigned char *seibuf, unsigned char *seiend) { unsigned char *tbuf = seibuf; while(tbuf < seiend - 1) // Use -1 because of trailing marker { tbuf = sei_message(ctx, tbuf, seiend - 1); } if(tbuf == seiend - 1 ) { if(*tbuf != 0x80) mprint("Strange rbsp_trailing_bits value: %02X\n",*tbuf); else dvprint("\n"); } else { // TODO: This really really looks bad mprint ("WARNING: Unexpected SEI unit length...trying to continue."); temp_debug = 1; mprint ("\n Failed block (at sei_rbsp) was:\n"); dump (CCX_DMT_GENERIC_NOTICES,(unsigned char *) seibuf, seiend-seibuf,0,0); ctx->num_unexpected_sei_length++; } }
double regularization_path(problem *prob, double epsilon, int nval) { int nr_folds = 5; double llog, error, best_error = DBL_MAX, lambda, best_lambda; double lmax, lmin, lstep; double *y_hat = dvector(1, prob->n); double *w = dvector(1, prob->dim); /* compute maximum lambda for which all weights are 0 (Osborne et al. 1999) * lambda_max = ||X'y||_inf. According to scikit-learn source code, you can * divide by npatterns and it still works */ dmvtransmult(prob->X, prob->n, prob->dim, prob->y, prob->n, w); lmax = dvnorm(w, prob->dim, INF) / prob->n; lmin = epsilon*lmax; lstep = (log2(lmax)-log2(lmin))/nval; fprintf(stdout, "lmax=%g lmin=%g epsilon=%g nval=%d\n", lmax, lmin, epsilon, nval); /* warm-starts: weights are set to 0 only at the begining */ dvset(w, prob->dim, 0); for(llog=log2(lmax); llog >= log2(lmin); llog -= lstep) { lambda = pow(2, llog); /*cross_validation(prob, w, lambda, 0, nr_folds, y_hat);*/ /*******************************************************/ int iter = 1000; double tol = 0, fret; fista(prob, w, lambda, 0, tol, 0, &iter, &fret); fista_predict(prob, w, y_hat); /*******************************************************/ error = mae(prob->y, prob->n, y_hat); fprintf(stdout, " lambda %10.6lf MAE %7.6lf active weights %d/%d\n", lambda, error, dvnotzero(w, prob->dim), prob->dim); dvprint(stdout, w, prob->dim); if (error < best_error) { best_error = error; best_lambda = lambda; } } free_dvector(y_hat, 1, prob->n); free_dvector(w, 1, prob->dim); print_line(60); fprintf(stdout, "\nBest: lambda=%g MAE=%g active weights=%d/%d\n", best_lambda, best_error, dvnotzero(w, prob->dim), prob->dim); return best_lambda; }
// This combines sei_message() and sei_payload(). unsigned char *sei_message (struct avc_ctx *ctx, unsigned char *seibuf, unsigned char *seiend) { int payloadType = 0; while (*seibuf==0xff) { payloadType+=255; seibuf++; } payloadType += *seibuf; seibuf++; int payloadSize = 0; while (*seibuf==0xff) { payloadSize+=255; seibuf++; } payloadSize += *seibuf; seibuf++; int broken=0; unsigned char *paystart = seibuf; seibuf+=payloadSize; dvprint("Payload type: %d size: %d - ", payloadType, payloadSize); if(seibuf > seiend ) { // TODO: What do we do here? broken=1; if (payloadType==4) { dbg_print(CCX_DMT_VERBOSE, "Warning: Subtitles payload seems incorrect (too long), continuing but it doesn't look good.."); } else { dbg_print(CCX_DMT_VERBOSE, "Warning: Non-subtitles payload seems incorrect (too long), continuing but it doesn't look good.."); } } dbg_print(CCX_DMT_VERBOSE, "\n"); // Ignore all except user_data_registered_itu_t_t35() payload if(!broken && payloadType == 4) user_data_registered_itu_t_t35(ctx, paystart, paystart+payloadSize); return seibuf; }
// Process inbuf bytes in buffer holding and AVC (H.264) video stream. // The number of processed bytes is returned. size_t process_avc ( struct lib_cc_decode *ctx, unsigned char *avcbuf, size_t avcbuflen ,struct cc_subtitle *sub) { unsigned char *bpos = avcbuf; unsigned char *NALstart; unsigned char *NALstop; // At least 5 bytes are needed for a NAL unit if(avcbuflen <= 5) { fatal(CCX_COMMON_EXIT_BUG_BUG, "NAL unit need at last 5 bytes ..."); } // Warning there should be only leading zeros, nothing else if( !(bpos[0]==0x00 && bpos[1]==0x00) ) { fatal(CCX_COMMON_EXIT_BUG_BUG, "Broken AVC stream - no 0x0000 ..."); } bpos = bpos+2; int firstloop=1; // Check for valid start code at buffer start // Loop over NAL units while(bpos < avcbuf + avcbuflen - 2) // bpos points to 0x01 plus at least two bytes { int zeropad=0; // Count leading zeros // Find next NALstart while (bpos < avcbuf + avcbuflen) { if(*bpos == 0x01) { // OK, found a start code break; } else if(firstloop && *bpos != 0x00) { // Not 0x00 or 0x01 fatal(CCX_COMMON_EXIT_BUG_BUG, "Broken AVC stream - no 0x00 ..."); } bpos++; zeropad++; } firstloop=0; if (bpos >= avcbuf + avcbuflen) { // No new start sequence break; } NALstart = bpos+1; // Find next start code or buffer end LLONG restlen; do { // Search for next 000000 or 000001 bpos++; restlen = avcbuf - bpos + avcbuflen - 2; // leave room for two more bytes // Find the next zero if (restlen > 0) { bpos = (unsigned char *) memchr (bpos, 0x00, (size_t) restlen); if(!bpos) { // No 0x00 till the end of the buffer NALstop = avcbuf + avcbuflen; bpos = NALstop; break; } if(bpos[1]==0x00 && (bpos[2]|0x01)==0x01) { // Found new start code NALstop = bpos; bpos = bpos + 2; // Move after the two leading 0x00 break; } } else { NALstop = avcbuf + avcbuflen; bpos = NALstop; break; } } while(restlen); // Should never be true - loop is exited via break if(*NALstart & 0x80) { dump(CCX_DMT_GENERIC_NOTICES, NALstart-4,10, 0, 0); fatal(CCX_COMMON_EXIT_BUG_BUG, "Broken AVC stream - forbidden_zero_bit not zero ..."); } ctx->avc_ctx->nal_ref_idc = *NALstart >> 5; dvprint("process_avc: zeropad %d\n", zeropad); do_NAL (ctx, NALstart, NALstop-NALstart, sub); } return avcbuflen; }
int main(int argc, char *argv[]) { char *ftest = NULL; struct timeval t0, t1, diff; problem *train, *test; int regpath_flag = 0, backtracking_flag = 0, std_flag = 1, verbose_flag = 0; int iter = 1000, c, crossval_flag = 0, nr_folds = 10, nval = 100, nzerow; double *w, *y_hat, *mean, *var; double lambda_1 = 1e-6, lambda_2 = 0, tol = 1e-9, epsilon, fret; while (1) { static struct option long_options[] = { /* These options don't set a flag. We distinguish them by their indices. */ {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, {"backtracking", no_argument, 0, 'b'}, {"original", no_argument, 0, 'o'}, {"test", required_argument, 0, 't'}, {"l1", required_argument, 0, 'l'}, {"l2", required_argument, 0, 'r'}, {"cross-validation", optional_argument, 0, 'c'}, {"tolerance ", optional_argument, 0, 'e'}, {"regpath", optional_argument, 0, 'p'}, /*{"stop", optional_argument, 0, 's'},*/ {"max-iters", optional_argument, 0, 'i'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "vhbot:r:l:p::c::e::s::i::", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch(c) { case 'h': exit_with_help(argv[PROG]); break; case 'b': backtracking_flag = 1; break; case 'v': verbose_flag = 1; break; case 'o': std_flag = 0; break; case 't': ftest = optarg; break; case 'c': crossval_flag = 1; if (optarg) if (sscanf(optarg, "%d", &nr_folds) != 1) { fprintf(stderr, "%s: option -c requires an int\n", argv[PROG]); exit_without_help(argv[PROG]); } break; case 'e': if (optarg) if (sscanf(optarg, "%lf", &tol) != 1) { fprintf(stderr, "%s: option -e requires a double\n", argv[PROG]); exit_without_help(argv[PROG]); } break; case 'p': regpath_flag = 1; if (optarg) if (sscanf(optarg, "%d", &nval) != 1) { fprintf(stderr, "%s: option -p requires an int\n", argv[PROG]); exit_without_help(argv[PROG]); } break; //case 's': // search_flag = 1; // if (optarg) // if (sscanf(optarg, "%lf:%d:%lf", &lmax, &nval, &lmin) != 3) // { // printf("%s\n", optarg); // fprintf(stderr, "%s: option -s requires a range in the format MAX:NVAL:MIN\n", argv[PROG]); // exit_without_help(argv[PROG]); // } // break; case 'l': if (sscanf(optarg, "%lf", &lambda_1) != 1) { fprintf(stderr, "%s: option -l requires a float\n", argv[PROG]); exit_without_help(argv[PROG]); } break; case 'r': if (sscanf(optarg, "%lf", &lambda_2) != 1) { fprintf(stderr, "%s: option -r requires a float\n", argv[PROG]); exit_without_help(argv[PROG]); } break; case 'i': if (optarg) if (sscanf(optarg, "%d", &iter) != 1) { fprintf(stderr, "%s: option -i requires an int\n", argv[PROG]); exit_without_help(argv[PROG]); } break; case '?': /* getopt_long already printed an error message. */ exit_without_help(argv[PROG]); break; default: printf("?? getopt returned character code 0%o ??\n", c); } } if ((argc - optind) < ARGC_MIN || (argc - optind) > ARGC_MAX) { fprintf(stderr, "%s: missing file operand\n", argv[PROG]); exit_without_help(argv[PROG]); } /* start time */ gettimeofday(&t0, 0); train = read_problem(argv[optind]); fprintf(stdout, "n:%d dim:%d\n", train->n, train->dim); /* alloc vector for means and variances, plus 1 for output */ if (std_flag) { fprintf(stdout, "Standarizing train set...\n"); mean = dvector(1, train->dim+1); var = dvector(1, train->dim+1); standarize(train, 1, mean, var); } if (ftest) { test = read_problem(ftest); if (std_flag) standarize(test, 0, mean, var); } if (regpath_flag) { fprintf(stdout, "Regularization path...\n"); /* in glmnet package they use 0.0001 instead of 0.001 ? */ epsilon = train->n > train->dim ? 0.001 : 0.01; lambda_1 = regularization_path(train, epsilon, nval); } fprintf(stdout, "lambda_1: %g\n", lambda_1); fprintf(stdout, "lambda_2: %g\n", lambda_2); /* initialize weight vector to 0 */ w = dvector(1, train->dim); dvset(w, train->dim, 0); fprintf(stdout, "Training model...\n"); if (backtracking_flag) /*fista_backtrack(train, w, lambda_1, lambda_2, tol, &iter, &fret);*/ fista_nocov(train, w, lambda_1, lambda_2, tol, &iter, &fret); else fista(train, w, lambda_1, lambda_2, tol, verbose_flag, &iter, &fret); y_hat = dvector(1, train->n); fista_predict(train, w, y_hat); nzerow = dvnotzero(w, train->dim); fprintf(stdout, "Iterations: %d\n", iter); fprintf(stdout, "Active weights: %d/%d\n", nzerow, train->dim); if (std_flag) fprintf(stdout, "MAE train: %g\n", var[train->dim+1]*mae(train->y, train->n, y_hat)); fprintf(stdout, "MAE train (standarized): %g\n", mae(train->y, train->n, y_hat)); free_dvector(y_hat, 1, train->n); if (crossval_flag) { dvset(w, train->dim, 0); y_hat = dvector(1, train->n); cross_validation(train, w, lambda_1, lambda_2, nr_folds, y_hat); fprintf(stdout, "MAE cross-validation: %lf\n", mae(train->y, train->n, y_hat)); free_dvector(y_hat, 1, train->n); } if (ftest) { /* we alloc memory again since test size is different from train size */ y_hat = dvector(1, test->n); fista_predict(test, w, y_hat); fprintf(stdout, "MAE test: %g\n", mae(test->y, test->n, y_hat)); free_dvector(y_hat, 1, test->n); } /* stop time */ gettimeofday(&t1, 0); timeval_subtract(&t1, &t0, &diff); fprintf(stdout, "Time(h:m:s.us): %02d:%02d:%02d.%06ld\n", diff.tv_sec/3600, (diff.tv_sec/60), diff.tv_sec%60, diff.tv_usec); if (verbose_flag) { fprintf(stdout, "Weights: "); dvprint(stdout, w, train->dim); } free_dvector(w, 1, train->dim); if (std_flag) { free_dvector(mean, 1, train->dim+1); free_dvector(var, 1, train->dim+1); } if (ftest) { free_dvector(test->y, 1, test->n); free_dmatrix(test->X, 1, test->n, 1, test->dim); free(test); } free_dvector(train->y, 1, train->n); free_dmatrix(train->X, 1, train->n, 1, train->dim); free(train); return 0; }