void* processing_routine(void* args) { //decoded video frame that will be pulled from the queue jakopter_video_frame_t frame; //wait for frames to be decoded, and then process them. pthread_mutex_lock(&mutex_stopped); while(!stopped) { pthread_mutex_unlock(&mutex_stopped); if(video_queue_pull_frame(&frame) < 0) { fprintf(stderr, "[Video Processing] Error retrieving frame !\n"); video_set_stopped(); } //a 0-sized frame means we're about to quit. else if(frame.size != 0) if(frame_processing_callback(frame.pixels, frame.w, frame.h, frame.size) < 0) { fprintf(stderr, "[Video Processing] Error processing frame !\n"); video_set_stopped(); } pthread_mutex_lock(&mutex_stopped); } pthread_mutex_unlock(&mutex_stopped); //free the resources of the processing module if(frame_processing_clean != NULL) frame_processing_clean(); pthread_exit(NULL); }
/* Decode a video buffer. Returns: 0 : buffer decoded, but no image produced (incomplete). > 0 : decoded n images. -1 : error while decoding. */ int video_decode_packet(uint8_t* buffer, int buf_size) { //number of bytes processed by the frame parser and the decoder int parsedLen = 0, decodedLen = 0; //do we have a whole frame ? int complete_frame = 0; //how many frames have we decoded ? int nb_frames = 0; if(buf_size <= 0 || buffer == NULL) return 0; //parse the video packet. If the parser returns a frame, decode it. while(buf_size > 0) { //1. parse the newly-received packet. If the parser has assembled a whole frame, store it in the video_packet structure. //TODO: confirm/infirm usefulness of frameOffset parsedLen = av_parser_parse2(cpContext, context, &video_packet.data, &video_packet.size, buffer, buf_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); //2. modify our buffer's data offset to reflect the parser's progression. buffer += parsedLen; buf_size -= parsedLen; frameOffset += parsedLen; //3. do we have a frame to decode ? if(video_packet.size > 0) { //printf("Packet size : %d\n", video_packet.size); decodedLen = avcodec_decode_video2(context, current_frame, &complete_frame, &video_packet); if(decodedLen < 0) { fprintf(stderr, "Error : couldn't decode frame.\n"); return 0; } //If we get there, we should've decoded a frame. if(complete_frame) { nb_frames++; //check if the video size has changed if(current_frame->width != current_width || current_frame->height != current_height) if(video_alloc_frame_buffer() < 0) { fprintf(stderr, "Error : couldn't allocate memory for decoding.\n"); return -1; } //write the raw frame data in our temporary buffer... int picsize = avpicture_layout((const AVPicture*)current_frame, current_frame->format, current_frame->width, current_frame->height, tempBuffer, tempBufferSize); //...that we then pass to the processing callback. if(frame_processing_callback(tempBuffer, current_frame->width, current_frame->height, picsize) < 0) return -1; //printf("Decoded frame : %d bytes, format : %d, size : %dx%d\n", picsize, current_frame->format, current_frame->width, current_frame->height); //free the frame's references for reuse av_frame_unref(current_frame); } //reinit frame offset for next frame frameOffset = 0; } } return nb_frames; }
void video_stop_decoder() { //Send a NULL buffer to the callback to indicate that we're done. frame_processing_callback(NULL, 0, 0, 0); avcodec_close(context); //quite recent and not very useful for us, always use avcodec_close for now. //avcodec_free_context(&context); av_parser_close(cpContext); av_frame_free(¤t_frame); if(tempBuffer != NULL) free(tempBuffer); }