void MassTrace::updateSmoothedMaxRT() { if (smoothed_intensities_.empty()) { throw Exception::InvalidValue(__FILE__, __LINE__, __PRETTY_FUNCTION__, "MassTrace was not smoothed before! Aborting...", String(smoothed_intensities_.size())); } double tmp_max(-1.0); Size max_idx(0); for (Size i = 0; i < smoothed_intensities_.size(); ++i) { if (smoothed_intensities_[i] > tmp_max) { tmp_max = smoothed_intensities_[i]; max_idx = i; } } if (tmp_max <= 0.0) { throw Exception::InvalidValue(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Negative max intensity encountered!", String(tmp_max)); } centroid_rt_ = trace_peaks_[max_idx].getRT(); }
Ptr<TrackerTargetState> TrackerStateEstimatorMILBoosting::estimateImpl( const std::vector<ConfidenceMap>& /*confidenceMaps*/) { //run ClfMilBoost classify in order to compute next location if( currentConfidenceMap.empty() ) return Ptr<TrackerTargetState>(); Mat positiveStates; Mat negativeStates; prepareData( currentConfidenceMap, positiveStates, negativeStates ); std::vector<float> prob = boostMILModel.classify( positiveStates ); int bestind = max_idx( prob ); //float resp = prob[bestind]; return currentConfidenceMap.at( bestind ).first; }
double MassTrace::estimateFWHM(bool use_smoothed_ints) { Size max_idx(this->findMaxByIntPeak(use_smoothed_ints)); std::vector<double> tmp_ints; if (use_smoothed_ints) { tmp_ints = smoothed_intensities_; } else { for (Size vec_idx = 0; vec_idx < trace_peaks_.size(); ++vec_idx) { tmp_ints.push_back(trace_peaks_[vec_idx].getIntensity()); } } double half_max_int(tmp_ints[max_idx] / 2.0); Size left_border(max_idx), right_border(max_idx); while (left_border > 0 && tmp_ints[left_border] >= half_max_int) { --left_border; } while (right_border + 1 < tmp_ints.size() && tmp_ints[right_border] >= half_max_int) { ++right_border; } fwhm_start_idx_ = left_border; fwhm_end_idx_ = right_border; fwhm_ = std::fabs(trace_peaks_[right_border].getRT() - trace_peaks_[left_border].getRT()); return fwhm_; }
Size MassTrace::findMaxByIntPeak(bool use_smoothed_ints) const { if (use_smoothed_ints && smoothed_intensities_.empty()) { throw Exception::InvalidValue(__FILE__, __LINE__, __PRETTY_FUNCTION__, "MassTrace was not smoothed before! Aborting...", String(smoothed_intensities_.size())); } if (trace_peaks_.empty()) { throw Exception::InvalidValue(__FILE__, __LINE__, __PRETTY_FUNCTION__, "MassTrace appears to be empty! Aborting...", String(trace_peaks_.size())); } double max_int; Size max_idx(0); if (use_smoothed_ints) { max_int = smoothed_intensities_[0]; } else { max_int = trace_peaks_.begin()->getIntensity(); } for (Size i = 0; i < trace_peaks_.size(); ++i) { double act_int = use_smoothed_ints ? smoothed_intensities_[i] : trace_peaks_[i].getIntensity(); if (act_int > max_int) { max_int = act_int; max_idx = i; } } return max_idx; }
double Tracker::update_location(Matrixu *img) { static SampleSet detectx; static vectorf prob; double resp; if (!img->isInitII()) abortError(__LINE__,__FILE__,"Integral image not initialized before calling update_location"); // run current clf on search window detectx.sampleImage(img, _x, _y, _w, _h, (float)_trparams->_srchwinsz); prob = _clf->classify(detectx,_trparams->_useLogR); // find best location int bestind = max_idx(prob); resp=prob[bestind]; _x = (float)detectx[bestind]._col; _y = (float)detectx[bestind]._row; // clean up detectx.clear(); return resp; }
/* * choose best audio and video streams, below bw. * 'header' is an asf header, and 'asf_header_size' is its size. * the result will be in 'streams' * return value: 1 ... success * -1 ... failed */ int asf_choose_best_streams(const uint8_t *header, int asf_header_size, int bw, struct asf_streams_t *streams) { int i = 0,pos = 0,start = 0; int *v_rates = NULL, *a_rates = NULL; int v_rate = 0, a_rate = 0, v_idx = -1, a_idx = -1; /* header is entire ASF header, including very first asf_header_t. */ pos = sizeof(struct asf_header_t); start = pos; /* choose best (fastest) streams */ while((pos = find_asf_guid(header,pos,asf_stream_header_guid,asf_header_size)) >= 0) { struct asf_stream_header_t *streamh = (struct asf_stream_header_t *)(header + pos); pos += sizeof(struct asf_stream_header_t); if(pos > asf_header_size) /* error */ return -1; /* get ASF GUID PREFIX (first 4 byte of GUID) */ switch(get32_le(streamh->type)) { case ASF_AUDIO_STREAM: /* audio stream */ display(MSDL_VER,"audio stream detected!!!!\n"); if(streams->audio_streams == NULL) { /* no audio stream registerd yet */ streams->audio_streams = (int *)xmalloc(sizeof(int)); streams->n_audio = 1; } else { /* more audio streams.!! */ streams->n_audio++; streams->audio_streams = (int *)xrealloc(streams->audio_streams, streams->n_audio * sizeof(int)); } streams->audio_streams[streams->n_audio - 1] = le2me_16(streamh->stream_no); break; case ASF_VIDEO_STREAM: /* video streams */ display(MSDL_VER,"video stream detected!!!!\n"); if(streams->video_streams == NULL) { /* no video stream registerd yet */ streams->video_streams = (int *)xmalloc(sizeof(int)); streams->n_video = 1; } else { /* more video streams.!! */ streams->n_video++; streams->video_streams = (int *)xrealloc(streams->video_streams, streams->n_video * sizeof(int)); } streams->video_streams[streams->n_video - 1] = le2me_16(streamh->stream_no); break; case ASF_COMMAND_MEDIA_STREAM: /* Command media stream... whatever*/ display(MSDL_VER,"Command media stream detected, but ignore this.\n"); break; case ASF_FILE_TRANSFER_MEDIA_STREAM: /* File transfer media stream... I don't know what the heck this is.*/ display(MSDL_VER,"File transfer stream detected, but ignore this.\n"); break; } } a_rates = (int *)xmalloc(streams->n_audio * sizeof(int)); v_rates = (int *)xmalloc(streams->n_video * sizeof(int)); pos = find_asf_guid(header,start,asf_stream_group_guid,asf_header_size); if(pos >= 0) { /* stream bitrate proterties object */ int stream_count = 0; uint8_t *ptr = (uint8_t *)header + pos; display(MSDL_VER,"stream bitrate properties object\n"); stream_count = get16_le(ptr); /* little endian. */ ptr += sizeof(uint16_t); if(ptr > header + asf_header_size) goto failed; display(MSDL_VER,"stream count = [0x%x] [%u]\n",stream_count,stream_count); display(MSDL_VER,"audio streams: %d, video streams: %d\n", streams->n_audio,streams->n_video); for(i = 0; i < stream_count; i++) { uint32_t rate = 0; int id = 0; int j = 0; id = get16_le(ptr); ptr += sizeof(uint16_t); if(ptr > header + asf_header_size) goto failed; rate = get32_le(ptr); ptr += sizeof(uint32_t); if(ptr > header + asf_header_size) goto failed; display(MSDL_VER, "stream_id = [0x%x] [%u]\n" "max bitrate = [0x%x] [%u]\n", id,id,rate,rate); for(j = 0; j < streams->n_audio; j++) { if(id == streams->audio_streams[j]) { display(MSDL_VER,"is audio stream\n"); a_rates[j] = rate; break; } } for(j = 0; j < streams->n_video; j++) { if(id == streams->video_streams[j]) { display(MSDL_VER,"is video stream\n"); v_rates[j] = rate; break; } } } } /* just to make sure bw is not Zero! */ if(bw == 0) { bw = INT_MAX_BANDWIDTH; } if(streams->n_audio) { /* find lowest-bitrate audio stream */ a_rate = a_rates[0]; a_idx = 0; for(i = 0; i < streams->n_audio; i++) { if(a_rates[i] < a_rate) { a_rate = a_rates[i]; a_idx = i; } } if(max_idx(streams->n_video,v_rates,bw - a_rate) < 0) { /* both audio and video are not possible, try video only next */ a_idx = -1; a_rate = 0; } } /* find best video stream */ v_idx = max_idx(streams->n_video,v_rates,bw - a_rate); if(v_idx >= 0) { v_rate = v_rates[v_idx]; } /* find best auido stream */ a_idx = max_idx(streams->n_audio,a_rates,bw - v_rate); free(v_rates); v_rates = NULL; free(a_rates); a_rates = NULL; if(a_idx < 0 && v_idx < 0) { display(MSDL_ERR,"bandwidth too low ... cannot get streams."); return -1; } if(a_idx >= 0) { streams->audio_id = streams->audio_streams[a_idx]; } else if(streams->n_audio) { display(MSDL_ERR,"Bandwidth too too small so deselected audio....sad.\n"); } if(v_idx >= 0) { streams->video_id = streams->video_streams[v_idx]; } else if(streams->n_video) { display(MSDL_ERR,"Bandwidth too too small so deselected video....sad.\n"); } return 1; failed: free(v_rates); free(a_rates); return -1; }
double SimpleTracker::track_frame(Matrixu &frame, Matrixu &framedisp) { static SampleSet posx, negx, detectx; static vectorf prob; static vectori order; static Matrixu *img; double resp; // copy a color version into framedisp (this is where we will draw a colored box around the object for output) frame.conv2RGB(framedisp); img = &frame; frame.initII(); // run current clf on search window detectx.sampleImage(img,(uint)_curState[0],(uint)_curState[1],(uint)_curState[2],(uint)_curState[3], (float)_trparams._srchwinsz); prob = _clf->classify(detectx,_trparams._useLogR); /////// DEBUG /////// display actual probability map if( _trparams._debugv ){ Matrixf probimg(frame.rows(),frame.cols()); for( uint k=0; k<(uint)detectx.size(); k++ ) probimg(detectx[k]._row, detectx[k]._col) = prob[k]; probimg.convert2img().display(2,2); cvWaitKey(1); } // find best location int bestind = max_idx(prob); resp=prob[bestind]; _curState[1] = (float)detectx[bestind]._row; _curState[0] = (float)detectx[bestind]._col; // train location clf (negx are randomly selected from image, posx is just the current tracker location) if( _trparams._negsamplestrat == 0 ) negx.sampleImage(img, _trparams._negnumtrain, (int)_curState[2], (int)_curState[3]); else negx.sampleImage(img, (int)_curState[0], (int)_curState[1], (int)_curState[2], (int)_curState[3], (1.5f*_trparams._srchwinsz), _trparams._posradtrain+5, _trparams._negnumtrain); if( _trparams._posradtrain == 1 ) posx.push_back(img, (int)_curState[0], (int)_curState[1], (int)_curState[2], (int)_curState[3]); else posx.sampleImage(img, (int)_curState[0], (int)_curState[1], (int)_curState[2], (int)_curState[3], _trparams._posradtrain, 0, _trparams._posmaxtrain); _clf->update(posx,negx); /////// DEBUG /////// display sampled negative points if( _trparams._debugv ){ for( int j=0; j<negx.size(); j++ ) framedisp.drawEllipse(1,1,(float)negx[j]._col,(float)negx[j]._row,1,255,0,255); } // clean up img->FreeII(); posx.clear(); negx.clear(); detectx.clear(); // draw a colored box around object framedisp.drawRect(_curState[2], _curState[3], _curState[0], _curState[1], 1, 0, _trparams._lineWidth, _trparams._boxcolor[0], _trparams._boxcolor[1], _trparams._boxcolor[2] ); _cnt++; return resp; }
void mlalign_TKF91(mlalign_Nucleotide *as, size_t na, mlalign_Nucleotide *bs, size_t nb, double lambda, double mu, double tau, double pi[mlalign_NUMBER_OF_BASES], mlalign_Site *alignment, size_t *n, double *score) { /***********************/ /* initialize matrices */ /***********************/ size_t rows = na + 1; size_t cols = nb + 1; auto idxM = diagonalizedIndexer(rows, cols, VECSIZE); auto idxA = identityIndexer(na); auto idxB = identityIndexer(nb); auto idxP1 = identityIndexer(mlalign_NUMBER_OF_BASES); auto idxP2 = rowMajorIndexer(mlalign_NUMBER_OF_BASES, mlalign_NUMBER_OF_BASES); auto idx2 = identityIndexer(2); // Allocate enough bytes for the matrices and properly align that. // We won't use vector because // 1) it initializes every element to 0 // 2) has some extra payload we won't need (e.g. capacity and size for bounds checks) // 3) we don't resize const size_t doubles_per_matrix = to_next_multiple(idxM(rows - 1, cols - 1) + 1, VECSIZE); std::unique_ptr<double[]> buffer(new double[3 * doubles_per_matrix + VECSIZE]); auto M0 = reinterpret_cast<double*>( to_next_multiple( reinterpret_cast<size_t>(buffer.get()), VECSIZE * sizeof(double))); auto M1 = M0 + doubles_per_matrix; auto M2 = M1 + doubles_per_matrix; assert(M0 - buffer.get() < static_cast<std::ptrdiff_t>(VECSIZE)); // // Memoization // const double beta = (1 - std::exp((lambda - mu) * tau)) / (mu - lambda * std::exp((lambda - mu) * tau)); const double delta = 1 / (1 - pi[0] * pi[0] - pi[1] * pi[1] - pi[2] * pi[2] - pi[3] * pi[3]); const double lambda_div_mu = lambda / mu; const double lambda_mul_beta = lambda * beta; double p_desc_1 = p_desc(1, beta, lambda, mu, tau); double M0_factor[mlalign_NUMBER_OF_BASES]; double M1_factor[mlalign_NUMBER_OF_BASES * mlalign_NUMBER_OF_BASES]; double M2_factor[mlalign_NUMBER_OF_BASES]; double p_desc_inv_n[2]; for (size_t i = 0; i < 2; ++i) { p_desc_inv_n[idx2(i)] = p_desc_inv(i, beta, lambda, mu, tau); } for (size_t i = 0; i < mlalign_NUMBER_OF_BASES; ++i) { const auto a = static_cast<mlalign_Nucleotide>(i); M0_factor[idxP1(a)] = std::log(lambda_div_mu * pi[idxP1(a)] * p_desc_inv_n[idx2(0)]); } for (size_t i = 0; i < mlalign_NUMBER_OF_BASES; ++i) { for (size_t j = 0; j < mlalign_NUMBER_OF_BASES; ++j) { const auto a = static_cast<mlalign_Nucleotide>(i); const auto b = static_cast<mlalign_Nucleotide>(j); M1_factor[idxP2(a, b)] = std::log(lambda_div_mu * pi[idxP1(a)] * std::max(p_trans(a, b, delta, pi, tau) * p_desc_1, pi[idxP1(b)] * p_desc_inv_n[idx2(1)])); } } for (size_t i = 0; i < mlalign_NUMBER_OF_BASES; ++i) { const auto b = static_cast<mlalign_Nucleotide>(i); M2_factor[idxP1(b)] = std::log(pi[idxP1(b)] * lambda_mul_beta); } size_t ix = idxM(0, 0); // We'll reuse ix throughout this function for caching idx calculations M0[ix] = -std::numeric_limits<double>::max(); M1[ix] = std::log(gamma2(0, lambda, mu) * zeta(1, beta, lambda)); M2[ix] = -std::numeric_limits<double>::max(); double accum = 0.0; for (size_t i = 1; i < rows; i++) { ix = idxM(i, 0); accum += std::log(pi[idxP1(as[idxA(i-1)])] * p_desc_inv_n[idx2(0)]); M0[ix] = std::log(gamma2(i, lambda, mu) * zeta(i, beta, lambda)) + accum; M1[ix] = -std::numeric_limits<double>::max(); M2[ix] = -std::numeric_limits<double>::max(); } accum = 0.0; for (size_t j = 1; j < cols; j++) { ix = idxM(0, j); accum += std::log(pi[idxP1(bs[idxB(j-1)])]); M0[ix] = -std::numeric_limits<double>::max(); M1[ix] = -std::numeric_limits<double>::max(); M2[ix] = std::log(gamma2(0, lambda, mu) * zeta(j + 1, beta, lambda)) + accum; } /****************/ /* DP algorithm */ /****************/ // TODO: Implement these in circular queues. size_t top[3] = { 0, 0, SIZE_MAX }; size_t bottom[3] { 1, 0, SIZE_MAX }; // This is tricky. We store the corrected offsets for diagonals offset -1 and -2 (7, 3 resp.) and the // uncorrected (e.g. not aligned) offset for the current diagonal (which is 7 + 2 = 9). // We inititialize with the values for diagonal 2, 1 and 0, we start at diagonal = 2 anyway. size_t diagonal_offsets[3] = { 2*VECSIZE + 1, 2*VECSIZE - 1, VECSIZE - 1 }; const size_t number_of_diagonals = rows + cols - 1; for (size_t diagonal = 2; diagonal < number_of_diagonals; ++diagonal) { // Topmost and bottommost row index of the diagonal, // skipping the already initialized first row and column (diagonal - 1 for that reason). // It's helpful for intuition to visualize this (rows=7, cols=6): // // 3 7 11 15 19 // 8 12 16 20 24 // 5 17 21 25 32 // 18 22 26 33 40 // 23 27 34 41 44 // 28 35 42 45 48 // 36 43 46 49 52 // // diagonal | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | // bottom_without_first | 1 | 2 | 3 | 4 | 5 | 6 | 6 | 6 | // top_without_first | 1 | 1 | 1 | 1 | 2 | 3 | 4 | 5 | // // We will then iterate over the diagonal through the indices // [top_without_first, bottom_without_first] inclusive. Column // indices are easily computed from the diagonal and row index. // We start with diagonal = 2, e.g. the third diagonal, because // it's the first containing uninitialized values. // const size_t bottom_without_first = std::min(diagonal - 1, rows - 1); const size_t top_without_first = diagonal - std::min(diagonal - 1, cols - 1); std::rotate(top, top + 2, top + 3); // This pushes all elements on further back std::rotate(bottom, bottom + 2, bottom + 3); bottom[0] = std::min(diagonal, rows - 1); top[0] = diagonal - std::min(diagonal, cols - 1); const size_t length_of_diagonal = bottom[0] + 1 - top[0]; // We have to correct the diagonal offset for the alignment rules layed out in diagonalizedIndexer. // 1. If the diagonal starts in the first row (top[0]=0), then the offset must have alignment -1. // 2. If the diagonal doesn't start in the first row, then the offset must have alignment 0. diagonal_offsets[0] += top[0] == 0 ? VECSIZE - 1 - diagonal_offsets[0] % VECSIZE : (VECSIZE - diagonal_offsets[0] % VECSIZE) % VECSIZE; assert((top[0] == 0 && diagonal_offsets[0] % VECSIZE == VECSIZE - 1) || (top[0] != 0 && diagonal_offsets[0] % VECSIZE == 0)); // INDEX EXPLANATIONS // row_offset offset of the row where the current SIMD vector begins // i index into the SIMD vector // col index of the column where the currently processed vector element is located in the DP matrix // row index of the row where the currently processed vector element is located in the DP matrix // Step in vector size over diagonal entries for (size_t row_offset = top_without_first; row_offset <= bottom_without_first; row_offset += VECSIZE) { // Copy the factors values from the lookuptable into the vector // Apparently it is not better to copy into temp memory and the use loaddvec, but it is faster to just use the [] operator. dvec factors[3]; for (size_t i = 0; i < VECSIZE; ++i) { const size_t row = row_offset + i; const size_t col = diagonal - row; if (row > bottom_without_first) { // We would load from somewhere out of the matrix, so we just leave the // other vector elements untouched break; } const mlalign_Nucleotide a = as[idxA(row - 1)]; const mlalign_Nucleotide b = bs[idxB(col - 1)]; factors[0][i] = M0_factor[idxP1(a)]; factors[1][i] = M1_factor[idxP2(a, b)]; factors[2][i] = M2_factor[idxP1(b)]; } // Compute the indexes of the top, left and top left cells and load them. const size_t ix_top = diagonal_offsets[1] + row_offset - 1 - top[1]; assert(ix_top == idxM(row_offset - 1, diagonal - row_offset)); const dvec max_top[3] = { loaddvec(M0 + ix_top), loaddvec(M1 + ix_top), loaddvec(M2 + ix_top), }; const size_t ix_topleft = diagonal_offsets[2] + row_offset - 1 - top[2]; assert(ix_topleft == idxM(row_offset - 1, diagonal - row_offset - 1)); const dvec max_topleft[3] = { loaddvec(M0 + ix_topleft), loaddvec(M1 + ix_topleft), loaddvec(M2 + ix_topleft), }; // Against all symmetry M0 isn't part of the formula. const size_t ix_left = ix_top + 1; assert(ix_left == idxM(row_offset, diagonal - row_offset - 1)); const dvec max_left[2] = { loaddvec(M1 + ix_left), loaddvec(M2 + ix_left), }; // Maxima for each cells on top/topleft/left of the calculated cell const dvec mt = maxdvec(max_top[0], maxdvec(max_top[1], max_top[2])); const dvec mtl = maxdvec(max_topleft[0], maxdvec(max_topleft[1], max_topleft[2])); const dvec ml = maxdvec(max_left[0], max_left[1]); // Vectorised add const dvec m0v = factors[0] + mt; const dvec m1v = factors[1] + mtl; const dvec m2v = factors[2] + ml; // Write back to matrix const size_t occupied_vector_elements = std::min(bottom_without_first + 1 - row_offset, VECSIZE); ix = diagonal_offsets[0] + row_offset - top[0]; assert(ix % VECSIZE == 0); assert(ix == idxM(row_offset, diagonal - row_offset)); storedvec(M0 + ix, m0v, occupied_vector_elements); storedvec(M1 + ix, m1v, occupied_vector_elements); storedvec(M2 + ix, m2v, occupied_vector_elements); } std::rotate(diagonal_offsets, diagonal_offsets + 2, diagonal_offsets + 3); diagonal_offsets[0] = diagonal_offsets[1] + length_of_diagonal; } /****************/ /* Backtracking */ /****************/ ix = idxM(na, nb); *n = 0; *score = std::exp(std::max({M0[ix], M1[ix], M2[ix]})); size_t cur = max_idx({M0[ix], M1[ix], M2[ix]}); for (size_t i = na, j = nb; i > 0 || j > 0;) { mlalign_Site site = {mlalign_Gap, mlalign_Gap}; switch (cur) { case 0: // insert assert(i > 0); site.a = as[--i]; site.b = mlalign_Gap; ix = idxM(i, j); cur = max_idx({M0[ix], M1[ix], M2[ix]}); break; case 1: // substitution assert(i > 0); assert(j > 0); site.a = as[--i]; site.b = bs[--j]; ix = idxM(i, j); cur = max_idx({M0[ix], M1[ix], M2[ix]}); break; case 2: // deletion assert(j > 0); site.a = mlalign_Gap; site.b = bs[--j]; ix = idxM(i, j); cur = max_idx({M1[ix], M2[ix]}) + 1; break; default: assert(0); } alignment[(*n)++] = site; // Doesn't get any scarier } // The alignment is reversed, so we have to undo that. for (size_t i = 0; i < (*n) / 2; ++i) { std::swap(alignment[i], alignment[*n - i - 1]); } }
static int asf_streaming_parse_header(int fd, streaming_ctrl_t* streaming_ctrl) { ASF_stream_chunck_t chunk; asf_http_streaming_ctrl_t* asf_ctrl = streaming_ctrl->data; char* buffer=NULL, *chunk_buffer=NULL; int i,r,size,pos = 0; int start; int buffer_size = 0; int chunk_size2read = 0; int bw = streaming_ctrl->bandwidth; int *v_rates = NULL, *a_rates = NULL; int v_rate = 0, a_rate = 0, a_idx = -1, v_idx = -1; if(asf_ctrl == NULL) return -1; // The ASF header can be in several network chunks. For example if the content description // is big, the ASF header will be split in 2 network chunk. // So we need to retrieve all the chunk before starting to parse the header. do { if (asf_read_wrapper(fd, &chunk, sizeof(ASF_stream_chunck_t), streaming_ctrl) <= 0) return -1; // Endian handling of the stream chunk le2me_ASF_stream_chunck_t(&chunk); size = asf_streaming( &chunk, &r) - sizeof(ASF_stream_chunck_t); if(r) mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_ASF_WarnDropHeader); if(size < 0){ mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader); return -1; } if (chunk.type != ASF_STREAMING_HEADER) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_NoHeaderAtFirstChunk); return -1; } // audit: do not overflow buffer_size if (size > SIZE_MAX - buffer_size) return -1; buffer = malloc(size+buffer_size); if(buffer == NULL) { mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MPDEMUX_ASF_BufferMallocFailed,size+buffer_size); return -1; } if( chunk_buffer!=NULL ) { memcpy( buffer, chunk_buffer, buffer_size ); free( chunk_buffer ); } chunk_buffer = buffer; buffer += buffer_size; buffer_size += size; if (asf_read_wrapper(fd, buffer, size, streaming_ctrl) <= 0) return -1; if( chunk_size2read==0 ) { ASF_header_t *asfh = (ASF_header_t *)buffer; if(size < (int)sizeof(ASF_header_t)) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunk2Small); return -1; } else mp_msg(MSGT_NETWORK,MSGL_DBG2,"Got chunk\n"); chunk_size2read = AV_RL64(&asfh->objh.size); mp_msg(MSGT_NETWORK,MSGL_DBG2,"Size 2 read=%d\n", chunk_size2read); } } while( buffer_size<chunk_size2read); buffer = chunk_buffer; size = buffer_size; start = sizeof(ASF_header_t); pos = find_asf_guid(buffer, asf_file_header_guid, start, size); if (pos >= 0) { ASF_file_header_t *fileh = (ASF_file_header_t *) &buffer[pos]; pos += sizeof(ASF_file_header_t); if (pos > size) goto len_err_out; /* if(fileh.packetsize != fileh.packetsize2) { printf("Error packetsize check don't match\n"); return -1; } */ asf_ctrl->packet_size = AV_RL32(&fileh->max_packet_size); // before playing. // preroll: time in ms to bufferize before playing streaming_ctrl->prebuffer_size = (unsigned int)(((double)fileh->preroll/1000.0)*((double)fileh->max_bitrate/8.0)); } pos = start; while ((pos = find_asf_guid(buffer, asf_stream_header_guid, pos, size)) >= 0) { ASF_stream_header_t *streamh = (ASF_stream_header_t *)&buffer[pos]; pos += sizeof(ASF_stream_header_t); if (pos > size) goto len_err_out; switch(ASF_LOAD_GUID_PREFIX(streamh->type)) { case 0xF8699E40 : // audio stream if(asf_ctrl->audio_streams == NULL){ asf_ctrl->audio_streams = malloc(sizeof(int)); asf_ctrl->n_audio = 1; } else { asf_ctrl->n_audio++; asf_ctrl->audio_streams = realloc(asf_ctrl->audio_streams, asf_ctrl->n_audio*sizeof(int)); } asf_ctrl->audio_streams[asf_ctrl->n_audio-1] = AV_RL16(&streamh->stream_no); break; case 0xBC19EFC0 : // video stream if(asf_ctrl->video_streams == NULL){ asf_ctrl->video_streams = malloc(sizeof(int)); asf_ctrl->n_video = 1; } else { asf_ctrl->n_video++; asf_ctrl->video_streams = realloc(asf_ctrl->video_streams, asf_ctrl->n_video*sizeof(int)); } asf_ctrl->video_streams[asf_ctrl->n_video-1] = AV_RL16(&streamh->stream_no); break; } } // always allocate to avoid lots of ifs later v_rates = calloc(asf_ctrl->n_video, sizeof(int)); a_rates = calloc(asf_ctrl->n_audio, sizeof(int)); pos = find_asf_guid(buffer, asf_stream_group_guid, start, size); if (pos >= 0) { // stream bitrate properties object int stream_count; char *ptr = &buffer[pos]; char *end = &buffer[size]; mp_msg(MSGT_NETWORK, MSGL_V, "Stream bitrate properties object\n"); if (ptr + 2 > end) goto len_err_out; stream_count = AV_RL16(ptr); ptr += 2; mp_msg(MSGT_NETWORK, MSGL_V, " stream count=[0x%x][%u]\n", stream_count, stream_count ); for( i=0 ; i<stream_count ; i++ ) { uint32_t rate; int id; int j; if (ptr + 6 > end) goto len_err_out; id = AV_RL16(ptr); ptr += 2; rate = AV_RL32(ptr); ptr += 4; mp_msg(MSGT_NETWORK, MSGL_V, " stream id=[0x%x][%u]\n", id, id); mp_msg(MSGT_NETWORK, MSGL_V, " max bitrate=[0x%x][%u]\n", rate, rate); for (j = 0; j < asf_ctrl->n_video; j++) { if (id == asf_ctrl->video_streams[j]) { mp_msg(MSGT_NETWORK, MSGL_V, " is video stream\n"); v_rates[j] = rate; break; } } for (j = 0; j < asf_ctrl->n_audio; j++) { if (id == asf_ctrl->audio_streams[j]) { mp_msg(MSGT_NETWORK, MSGL_V, " is audio stream\n"); a_rates[j] = rate; break; } } } } free(buffer); // automatic stream selection based on bandwidth if (bw == 0) bw = INT_MAX; mp_msg(MSGT_NETWORK, MSGL_V, "Max bandwidth set to %d\n", bw); if (asf_ctrl->n_audio) { // find lowest-bitrate audio stream a_rate = a_rates[0]; a_idx = 0; for (i = 0; i < asf_ctrl->n_audio; i++) { if (a_rates[i] < a_rate) { a_rate = a_rates[i]; a_idx = i; } } if (max_idx(asf_ctrl->n_video, v_rates, bw - a_rate) < 0) { // both audio and video are not possible, try video only next a_idx = -1; a_rate = 0; } } // find best video stream v_idx = max_idx(asf_ctrl->n_video, v_rates, bw - a_rate); if (v_idx >= 0) v_rate = v_rates[v_idx]; // find best audio stream a_idx = max_idx(asf_ctrl->n_audio, a_rates, bw - v_rate); free(v_rates); free(a_rates); if (a_idx < 0 && v_idx < 0) { mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_Bandwidth2SmallCannotPlay); return -1; } if (audio_id > 0) // a audio stream was forced asf_ctrl->audio_id = audio_id; else if (a_idx >= 0) asf_ctrl->audio_id = asf_ctrl->audio_streams[a_idx]; else if (asf_ctrl->n_audio) { mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedAudio); audio_id = -2; } if (video_id > 0) // a video stream was forced asf_ctrl->video_id = video_id; else if (v_idx >= 0) asf_ctrl->video_id = asf_ctrl->video_streams[v_idx]; else if (asf_ctrl->n_video) { mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedVideo); video_id = -2; } return 1; len_err_out: mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_InvalidLenInHeader); free(buffer); free(v_rates); free(a_rates); return -1; }