explicit implementation(const safe_ptr<AVFormatContext>& context) : codec_context_(open_codec(*context, AVMEDIA_TYPE_VIDEO, index_)) , nb_frames_(static_cast<uint32_t>(context->streams[index_]->nb_frames)) , width_(codec_context_->width) , height_(codec_context_->height) { file_frame_number_ = 0; }
static AVCodecContext *open_decoder(SCM scm_self, SCM scm_file_name, AVStream *stream, const char *media_type) { AVCodecContext *dec_ctx = stream->codec; AVCodec *decoder = avcodec_find_decoder(dec_ctx->codec_id); if (!decoder) { ffmpeg_destroy(scm_self); scm_misc_error("open-codec", "Failed to find ~a codec for file '~a'", scm_list_2(scm_from_locale_string(media_type), scm_file_name)); }; return open_codec(scm_self, dec_ctx, decoder, media_type, scm_file_name); }
bool OStreamVideoEncoder::encoder_initialize () { char *encoding_str; // register all codecs av_register_all(); switch ( _encoding_type ) { case OSTREAM_ENCODING_MJPEG: encoding_str = "mjpeg"; _out_fmt = guess_format ( encoding_str, NULL, NULL); if( !_out_fmt ) { // DEBUG_PRINT( "Could not find suitable output format.\n"); return false; } break; case OSTREAM_ENCODING_H263P: encoding_str ="h263"; _out_fmt = guess_format ( encoding_str, NULL, NULL); if( !_out_fmt ) { // DEBUG_PRINT( "Could not find suitable output format.\n"); return false; } // specify the sub-codec we want to use. Without this we won't be able // to stream H263P not use 640x480 videos _out_fmt->video_codec = CODEC_ID_H263P; break; default: // DEBUG_PRINT ("could not find known OSTREAM_ENCODING type.\n" ); break; } _out_fmt_context = av_alloc_format_context (); if( !_out_fmt_context ) { // DEBUG_PRINT( "Memory error.\n" ); return false; } // set output format of AVFormatContext _out_fmt_context->oformat = _out_fmt; // check if we had a correct video_codec if ( _out_fmt->video_codec == CODEC_ID_NONE ) { // DEBUG_PRINT( "CODEC_ID_NONE\n" ); return false; } // add the stream if(!( _video_stream = create_video_stream( _out_fmt_context, _out_fmt->video_codec ) )) { // DEBUG_PRINT( "error in adding stream\n" ); return false; } // set the output parameters (must be done even if no parameters) if ( av_set_parameters( _out_fmt_context, NULL ) < 0 ) { // DEBUG_PRINT( "Invalid output format parameters\n" ); return false; } // open codec associated with current video_stream if ( !open_codec( _video_stream ) ) { // DEBUG_PRINT( "could not open codec\n" ); return false; } // we should now create the frame on which we can store the converted bytes // ready to be encoded _ready_to_encode_frame = create_avframe( _video_stream->codec->pix_fmt,this->_video_width,this->_video_height ); if ( !_ready_to_encode_frame ) { // DEBUG_PRINT( "Could not allocate encoded_frame\n" ); return false; } // we'll receive IplImage(s). This _opencv_frame will be converted to a stream-compatible // AVFrame [see up _ready_to_encode_frame] _opencv_frame = NULL; return true; }
static GstFlowReturn gst_vp9_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) { GstVP9Dec *dec; GstFlowReturn ret = GST_FLOW_OK; vpx_codec_err_t status; vpx_codec_iter_t iter = NULL; vpx_image_t *img; long decoder_deadline = 0; GstClockTimeDiff deadline; GstMapInfo minfo; GST_DEBUG_OBJECT (decoder, "handle_frame"); dec = GST_VP9_DEC (decoder); if (!dec->decoder_inited) { ret = open_codec (dec, frame); if (ret == GST_FLOW_CUSTOM_SUCCESS_1) return GST_FLOW_OK; else if (ret != GST_FLOW_OK) return ret; } deadline = gst_video_decoder_get_max_decode_time (decoder, frame); if (deadline < 0) { decoder_deadline = 1; } else if (deadline == G_MAXINT64) { decoder_deadline = 0; } else { decoder_deadline = MAX (1, deadline / GST_MSECOND); } if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) { GST_ERROR_OBJECT (dec, "Failed to map input buffer"); return GST_FLOW_ERROR; } status = vpx_codec_decode (&dec->decoder, minfo.data, minfo.size, NULL, decoder_deadline); gst_buffer_unmap (frame->input_buffer, &minfo); if (status) { GST_VIDEO_DECODER_ERROR (decoder, 1, LIBRARY, ENCODE, ("Failed to decode frame"), ("%s", gst_vpx_error_name (status)), ret); return ret; } img = vpx_codec_get_frame (&dec->decoder, &iter); if (img) { GstVideoFormat fmt; switch (img->fmt) { case VPX_IMG_FMT_I420: fmt = GST_VIDEO_FORMAT_I420; break; case VPX_IMG_FMT_YV12: fmt = GST_VIDEO_FORMAT_YV12; break; case VPX_IMG_FMT_I422: fmt = GST_VIDEO_FORMAT_Y42B; break; case VPX_IMG_FMT_I444: fmt = GST_VIDEO_FORMAT_Y444; break; default: vpx_img_free (img); GST_ELEMENT_ERROR (decoder, LIBRARY, ENCODE, ("Failed to decode frame"), ("Unsupported color format %d", img->fmt)); return GST_FLOW_ERROR; break; } if (!dec->output_state || dec->output_state->info.finfo->format != fmt || dec->output_state->info.width != img->d_w || dec->output_state->info.height != img->d_h) { gboolean send_tags = !dec->output_state; if (dec->output_state) gst_video_codec_state_unref (dec->output_state); dec->output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), fmt, img->d_w, img->d_h, dec->input_state); gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec)); if (send_tags) gst_vp9_dec_send_tags (dec); } if (deadline < 0) { GST_LOG_OBJECT (dec, "Skipping late frame (%f s past deadline)", (double) -deadline / GST_SECOND); gst_video_decoder_drop_frame (decoder, frame); } else { ret = gst_video_decoder_allocate_output_frame (decoder, frame); if (ret == GST_FLOW_OK) { gst_vp9_dec_image_to_buffer (dec, img, frame->output_buffer); ret = gst_video_decoder_finish_frame (decoder, frame); } else { gst_video_decoder_drop_frame (decoder, frame); } } vpx_img_free (img); while ((img = vpx_codec_get_frame (&dec->decoder, &iter))) { GST_WARNING_OBJECT (decoder, "Multiple decoded frames... dropping"); vpx_img_free (img); } } else { /* Invisible frame */ GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame); gst_video_decoder_finish_frame (decoder, frame); } return ret; }
SCM make_ffmpeg_output(SCM scm_file_name, SCM scm_format_name, SCM scm_video_parameters, SCM scm_have_video, SCM scm_audio_parameters, SCM scm_have_audio, SCM scm_debug) { SCM retval; struct ffmpeg_t *self; scm_dynwind_begin(0); const char *file_name = scm_to_locale_string(scm_file_name); scm_dynwind_free(file_name); self = (struct ffmpeg_t *)scm_gc_calloc(sizeof(struct ffmpeg_t), "ffmpeg"); self->video_stream_idx = -1; self->audio_stream_idx = -1; SCM_NEWSMOB(retval, ffmpeg_tag, self); int err; const char *format_name = NULL; if (!scm_is_false(scm_format_name)) { format_name = scm_to_locale_string(scm_symbol_to_string(scm_format_name)); scm_dynwind_free(format_name); }; #ifdef HAVE_AVFORMAT_ALLOC_OUTPUT_CONTEXT2 err = avformat_alloc_output_context2(&self->fmt_ctx, NULL, format_name, file_name); if (!self->fmt_ctx) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error initializing output format for file '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); }; #else AVOutputFormat *format; if (format_name) format = av_guess_format(format_name, NULL, NULL); else format = av_guess_format(NULL, file_name, NULL); if (!format) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Unable to determine file format for file '~a'", scm_list_1(scm_file_name)); }; self->fmt_ctx = avformat_alloc_context(); if (!self->fmt_ctx) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error initializing output format for file '~a'", scm_list_1(scm_file_name)); }; self->fmt_ctx->oformat = format; strncpy(self->fmt_ctx->filename, file_name, sizeof(self->fmt_ctx->filename)); #endif char have_video = scm_is_true(scm_have_video); if (have_video) { // Open codec and video stream enum AVCodecID video_codec_id = self->fmt_ctx->oformat->video_codec; AVCodec *video_encoder = find_encoder(retval, video_codec_id, "video"); AVStream *video_stream = open_output_stream(retval, video_encoder, &self->video_stream_idx, "video", scm_file_name); // Get video parameters SCM scm_shape = scm_car(scm_video_parameters); SCM scm_frame_rate = scm_cadr(scm_video_parameters); SCM scm_video_bit_rate = scm_caddr(scm_video_parameters); SCM scm_aspect_ratio = scm_cadddr(scm_video_parameters); // Configure the output video codec self->video_codec_ctx = configure_output_video_codec(video_stream, video_codec_id, scm_video_bit_rate, scm_shape, scm_frame_rate, scm_aspect_ratio); // Some formats want stream headers to be separate. if (self->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) self->video_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // Open output video codec open_codec(retval, self->video_codec_ctx, video_encoder, "video", scm_file_name); // Allocate frame self->video_target_frame = allocate_output_video_frame(retval, self->video_codec_ctx); }; char have_audio = scm_is_true(scm_have_audio); if (have_audio) { // Open audio codec and stream enum AVCodecID audio_codec_id = self->fmt_ctx->oformat->audio_codec; AVCodec *audio_encoder = find_encoder(retval, audio_codec_id, "audio"); AVStream *audio_stream = open_output_stream(retval, audio_encoder, &self->audio_stream_idx, "audio", scm_file_name); // Get audio parameters SCM scm_select_rate = scm_car(scm_audio_parameters); SCM scm_channels = scm_cadr(scm_audio_parameters); SCM scm_audio_bit_rate = scm_caddr(scm_audio_parameters); SCM scm_select_format = scm_cadddr(scm_audio_parameters); // Configure the output audio codec self->audio_codec_ctx = configure_output_audio_codec(retval, audio_stream, audio_codec_id, scm_select_rate, scm_channels, scm_audio_bit_rate, scm_select_format); // Some formats want stream headers to be separate. if (self->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) self->audio_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // Open output audio codec open_codec(retval, self->audio_codec_ctx, audio_encoder, "audio", scm_file_name); // Allocate audio frame self->audio_target_frame = allocate_output_audio_frame(retval, self->audio_codec_ctx, self->audio_codec_ctx->sample_fmt); self->audio_packed_frame = allocate_output_audio_frame(retval, self->audio_codec_ctx, av_get_packed_sample_fmt(self->audio_codec_ctx->sample_fmt)); // Initialise audio buffer ringbuffer_init(&self->audio_buffer, 1024); }; if (scm_is_true(scm_debug)) av_dump_format(self->fmt_ctx, 0, file_name, 1); // Open the output file if needed if (!(self->fmt_ctx->oformat->flags & AVFMT_NOFILE)) { int err = avio_open(&self->fmt_ctx->pb, file_name, AVIO_FLAG_WRITE); if (err < 0) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Could not open '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); } self->output_file = 1; } // Write video file header err = avformat_write_header(self->fmt_ctx, NULL); if (err < 0) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error writing header of video '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); }; self->header_written = 1; scm_dynwind_end(); return retval; }