Recherche avancée

Médias (29)

Mot : - Tags -/Musique

Autres articles (15)

  • Des sites réalisés avec MediaSPIP

    2 mai 2011, par

    Cette page présente quelques-uns des sites fonctionnant sous MediaSPIP.
    Vous pouvez bien entendu ajouter le votre grâce au formulaire en bas de page.

  • Organiser par catégorie

    17 mai 2013, par

    Dans MédiaSPIP, une rubrique a 2 noms : catégorie et rubrique.
    Les différents documents stockés dans MédiaSPIP peuvent être rangés dans différentes catégories. On peut créer une catégorie en cliquant sur "publier une catégorie" dans le menu publier en haut à droite ( après authentification ). Une catégorie peut être rangée dans une autre catégorie aussi ce qui fait qu’on peut construire une arborescence de catégories.
    Lors de la publication prochaine d’un document, la nouvelle catégorie créée sera proposée (...)

  • Les thèmes de MediaSpip

    4 juin 2013

    3 thèmes sont proposés à l’origine par MédiaSPIP. L’utilisateur MédiaSPIP peut rajouter des thèmes selon ses besoins.
    Thèmes MediaSPIP
    3 thèmes ont été développés au départ pour MediaSPIP : * SPIPeo : thème par défaut de MédiaSPIP. Il met en avant la présentation du site et les documents média les plus récents ( le type de tri peut être modifié - titre, popularité, date) . * Arscenic : il s’agit du thème utilisé sur le site officiel du projet, constitué notamment d’un bandeau rouge en début de page. La structure (...)

Sur d’autres sites (4698)

  • How to encode using the FFMpeg in Android (using H263)

    3 juillet 2012, par Kenny910

    I am trying to follow the sample code on encoding in the ffmpeg document and successfully build a application to encode and generate a mp4 file but I face the following problems :

    1) I am using the H263 for encoding but I can only set the width and height of the AVCodecContext to 176x144, for other case (like 720x480 or 640x480) it will return fail.

    2) I can't play the output mp4 file by using the default Android player, isn't it support H263 mp4 file ? p.s. I can play it by using other player

    3) Is there any sample code on encoding other video frame to make a new video (which mean decode the video and encode it back in different quality setting, also i would like to modify the frame content) ?

    Here is my code, thanks !

    JNIEXPORT jint JNICALL Java_com_ffmpeg_encoder_FFEncoder_nativeEncoder(JNIEnv* env, jobject thiz, jstring filename){

    LOGI("nativeEncoder()");

    avcodec_register_all();
    avcodec_init();
    av_register_all();

    AVCodec         *codec;
    AVCodecContext  *codecCtx;
    int             i;
    int             out_size;
    int             size;
    int             x;
    int             y;
    int             output_buffer_size;
    FILE            *file;
    AVFrame         *picture;
    uint8_t         *output_buffer;
    uint8_t         *picture_buffer;

    /* Manual Variables */
    int             l;
    int             fps = 30;
    int             videoLength = 5;

    /* find the H263 video encoder */
    codec = avcodec_find_encoder(CODEC_ID_H263);
    if (!codec) {
       LOGI("avcodec_find_encoder() run fail.");
    }

    codecCtx = avcodec_alloc_context();
    picture = avcodec_alloc_frame();

    /* put sample parameters */
    codecCtx->bit_rate = 400000;
    /* resolution must be a multiple of two */
    codecCtx->width = 176;
    codecCtx->height = 144;
    /* frames per second */
    codecCtx->time_base = (AVRational){1,fps};
    codecCtx->pix_fmt = PIX_FMT_YUV420P;
    codecCtx->codec_id = CODEC_ID_H263;
    codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;

    /* open it */
    if (avcodec_open(codecCtx, codec) < 0) {
       LOGI("avcodec_open() run fail.");
    }

    const char* mfileName = (*env)->GetStringUTFChars(env, filename, 0);

    file = fopen(mfileName, "wb");
    if (!file) {
       LOGI("fopen() run fail.");
    }

    (*env)->ReleaseStringUTFChars(env, filename, mfileName);

    /* alloc image and output buffer */
    output_buffer_size = 100000;
    output_buffer = malloc(output_buffer_size);

    size = codecCtx->width * codecCtx->height;
    picture_buffer = malloc((size * 3) / 2); /* size for YUV 420 */

    picture->data[0] = picture_buffer;
    picture->data[1] = picture->data[0] + size;
    picture->data[2] = picture->data[1] + size / 4;
    picture->linesize[0] = codecCtx->width;
    picture->linesize[1] = codecCtx->width / 2;
    picture->linesize[2] = codecCtx->width / 2;

    for(l=0;l/encode 1 second of video
       for(i=0;i/prepare a dummy image YCbCr
           //Y
           for(y=0;yheight;y++) {
               for(x=0;xwidth;x++) {
                   picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
               }
           }

           //Cb and Cr
           for(y=0;yheight/2;y++) {
               for(x=0;xwidth/2;x++) {
                   picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
                   picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
               }
           }

           //encode the image
           out_size = avcodec_encode_video(codecCtx, output_buffer, output_buffer_size, picture);
           fwrite(output_buffer, 1, out_size, file);
       }

       //get the delayed frames
       for(; out_size; i++) {
           out_size = avcodec_encode_video(codecCtx, output_buffer, output_buffer_size, NULL);
           fwrite(output_buffer, 1, out_size, file);
       }
    }

    //add sequence end code to have a real mpeg file
    output_buffer[0] = 0x00;
    output_buffer[1] = 0x00;
    output_buffer[2] = 0x01;
    output_buffer[3] = 0xb7;

    fwrite(output_buffer, 1, 4, file);
    fclose(file);
    free(picture_buffer);
    free(output_buffer);
    avcodec_close(codecCtx);
    av_free(codecCtx);
    av_free(picture);

    LOGI("finish");

    return 0; }
  • Encoding using ffmpeg library fails

    29 septembre 2012, par Erik Swansson

    I've spent some time looking at the ffmpeg library and setting things up, I'm opening a .flv file. Reading and decoding and the frames, now I'm trying to encode it to MP4 but my packets end up empty.

    My code as follows

    int main (){

       avformat_open_input(&pFC, "c://wav//test2.flv", NULL, NULL);

       po = av_find_stream_info(pFC);

       //ADD LOGIC TO FIND VIDEO STREAM
       pCodecC = pFC->streams[0]->codec;

       decoder = avcodec_find_decoder(pCodecC->codec_id);
       encoder = avcodec_find_encoder(pCodecC->codec_id);
       po = avcodec_open(pCodecC, decoder);

       pCodecE =  avcodec_alloc_context3(encoder);
       /* put sample parameters */
       pCodecE->bit_rate = 400000;
       /* resolution must be a multiple of two */
       pCodecE->width = 352;
       pCodecE->height = 288;
       /* frames per second */
       pCodecE->time_base.den = 25;
       pCodecE->time_base.num = 1;
       pCodecE->gop_size = 10; /* emit one intra frame every ten frames */
       pCodecE->max_b_frames=1;
       pCodecE->pix_fmt = PIX_FMT_YUV420P;

       if(pCodecC->codec_id == CODEC_ID_H264)
           av_opt_set(pCodecE->priv_data, "preset", "slow", 0);

       po =  avcodec_open2(pCodecE, encoder, NULL);

       AVFrame *pFrame;
       // Allocate an AVFrame structure



       // Allocate video frame
       pFrame=avcodec_alloc_frame();
       int frameFinished = 0;
       int frame = 0;
       int gotpacket = 0;

       while(av_read_frame(pFC, &packet) >= 0)
       {
           if(packet.stream_index==0) //the video stream is 0
           {
               int len = avcodec_decode_video2(pCodecC, pFrame, &frameFinished, &packet);
               if(frameFinished)
               {
                   printf("frame # %i", frame);

                   po =avcodec_encode_video2(pCodecE, &spacket, pFrame, &gotpacket);
                   if(gotpacket)
                   {
                       printf("packet recieved");
                   }
                   frame++;
               }
           }
           av_free_packet(&packet);
       }


       printf("encoding done");

       return 0;
    }

    Basically everything works up to

    po =avcodec_encode_video2(pCodecE, &spacket, pFrame, &gotpacket);

    Where &gotpacket returns 0, as in an empty frame.

    Not sure what I'm doing wrong.

  • Sending raw h264 video and aac audio frames to an RTMP server using ffmpeg

    15 août 2016, par codeimpaler

    I am receiving raw h264 and aac audio frames from an even driven source. I am trying to send these frames to an rtmp server.
    I started working from the ffmpeg example muxing.c which successfully sends a custom stream to the rtmp server. I figure I just need to replace their frame data with my own.I found this suggestion online. I have tried How to pack raw h264 stream to flv container and send over rtmp using ffmpeg (not command)
    and
    How to publish selfmade stream with ffmpeg and c++ to rtmp server ?
    and a few other suggestions but none have worked for me.
    I have tried to directly memcpy my byte buffer but my code keeps failing
    at ret = avcodec_encode_video2(c, &pkt, frame, &got_packet).
    Specifically, I get an invalid access error.
    For a little more context, anytime I receive a frame (which is event driven), void RTMPWriter::WriteVideoFrame(...) is called. Assume the constructor has already been called before the first frame is received.
    I am not that familiar with ffmpeg and there could be several things wrong with the code. Any input will be really appreciated.

       #define STREAM_FRAME_RATE 25 /* 25 images/s */
       #define STREAM_PIX_FMT    AV_PIX_FMT_YUV420P /* default pix_fmt */
       #define SCALE_FLAGS SWS_BICUBIC
       RTMPWriter::RTMPWriter()
         : seenKeyFrame(false),
           video_st({ 0 }),
           audio_st({ 0 }),
           have_video(0),
           have_audio(0)
       {

           const char *filename;
           AVCodec *audio_codec = NULL, *video_codec = NULL;
           int ret;

           int encode_video = 0, encode_audio = 0;
           AVDictionary *opt = NULL;
           int i;

           /* Initialize libavcodec, and register all codecs and formats. */
           av_register_all();

           avformat_network_init();

          String^ StreamURL = "StreamURL";
          String^ out_uri = safe_cast(ApplicationData::Current->LocalSettings->Values->Lookup(StreamURL));
          std::wstring out_uriW(out_uri->Begin());
          std::string out_uriA(out_uriW.begin(), out_uriW.end());
          filename = out_uriA.c_str();  

          /* allocate the output media context */
          avformat_alloc_output_context2(&oc, NULL, "flv", filename);
          if (!oc)
          {
              OutputDebugString(L"Could not deduce output format from file extension: using MPEG.\n");
              avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
          }
          if (!oc)
          {
              OutputDebugString(L"Could not allocate  using MPEG.\n");
          }


          fmt = oc->oformat;

          /* Add the audio and video streams using the default format codecs
          * and initialize the codecs. */
          if (fmt->video_codec != AV_CODEC_ID_NONE) {
              add_stream(&video_st, oc, &video_codec, fmt->video_codec);
              have_video = 1;
              encode_video = 1;
          }
          if (fmt->audio_codec != AV_CODEC_ID_NONE) {
              add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec);
              have_audio = 1;
              encode_audio = 1;
          }

          /* Now that all the parameters are set, we can open the audio and
           * video codecs and allocate the necessary encode buffers. */
          if (have_video)
          {
              open_video(oc, video_codec, &video_st, opt);
          }

          if (have_audio)
          {
              open_audio(oc, audio_codec, &audio_st, opt);
          }

          av_dump_format(oc, 0, filename, 1);

          /* open the output file, if needed */
          if (!(fmt->flags & AVFMT_NOFILE))
          {
              ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
              if (ret < 0)
              {
                  OutputDebugString(L"Could not open ");
                  OutputDebugString(out_uri->Data());
              }
          }

          /* Write the stream header, if any. */
          ret = avformat_write_header(oc, &opt);
          if (ret < 0)
          {
              OutputDebugString(L"Error occurred when writing stream header \n");
          }

       }

       void RTMPWriter::WriteVideoFrame(
           boolean isKeyFrame,
           boolean hasDiscontinuity,
           UINT64 frameId,
           UINT32 videoBufferLength,
           BYTE *videoBytes)
       {

           int ret;
           AVCodecContext *c;
           AVFrame* frame;
           int got_packet = 0;
           AVPacket pkt = { 0 };

           c = video_st.enc;

           frame = get_video_frame(videoBufferLength, videoBytes);

           /* encode the image */
           ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
           if (ret < 0) {
                OutputDebugString(L"Error encoding video frame: \n")
           }

           if (got_packet)
           {
               ret = write_frame(oc, &c->time_base, video_st.st, &pkt);
           }
           else {
               ret = 0;
           }

           if (ret < 0) {
                OutputDebugString(L"Error while writing video frame: %s\n");
           }
       }

       AVFrame * RTMPWriter::get_video_frame(
          UINT32 videoBufferLength,
          BYTE *videoBytes)
       {
           AVCodecContext *c = video_st.enc;

           if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
               /* as we only generate a YUV420P picture, we must convert it
               * to the codec pixel format if needed */
               if (!video_st.sws_ctx) {
                   video_st.sws_ctx = sws_getContext(c->width, c->height,
                       AV_PIX_FMT_YUV420P,
                       c->width, c->height,
                       c->pix_fmt,
                       SCALE_FLAGS, NULL, NULL, NULL);
                   if (!video_st.sws_ctx) {
                       fprintf(stderr,
                           "Could not initialize the conversion context\n");
                           exit(1);
                   }
               }
               fill_yuv_image(video_st.tmp_frame, video_st.next_pts, c->width, c->height, videoBufferLength, videoBytes);
               sws_scale(video_st.sws_ctx,
               (const uint8_t * const *)video_st.tmp_frame->data, video_st.tmp_frame->linesize,
               0, c->height, video_st.frame->data, video_st.frame->linesize);
           }
           else {
               fill_yuv_image(video_st.frame, video_st.next_pts, c->width, c->height, videoBufferLength, videoBytes);
           }

           video_st.frame->pts = video_st.next_pts++;

           return video_st.frame;
       }

       /* Prepare a dummy image. */
       void  RTMPWriter::fill_yuv_image(
            AVFrame *pict,
            int frame_index,
            int width,
            int height,
            UINT32 videoBufferLength,
            BYTE *videoBytes)
       {
           //int x, y, i, ret;

           /* when we pass a frame to the encoder, it may keep a reference to it
           * internally;
           * make sure we do not overwrite it here
           */
           ret = av_frame_make_writable(pict);
           if (ret < 0)
           {
                OutputDebugString(L"Unable to make piture writable");
           }

           memcpy(pict->data, videoBytes, videoBufferLength);

           //i = frame_index;

           ///* Y */
           //for (y = 0; y < height; y++)
           //  for (x = 0; x < width; x++)
           //      pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;

           ///* Cb and Cr */
           //for (y = 0; y < height / 2; y++) {
           //  for (x = 0; x < width / 2; x++) {
           //      pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
           //      pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
           //  }
           //}
       }

       void RTMPWriter::WriteAudioFrame()
       {

       }

       /* Add an output stream. */
       void  RTMPWriter::add_stream(
           OutputStream *ost,
           AVFormatContext *oc,
           AVCodec **codec,
           enum AVCodecID codec_id)
      {
       AVCodecContext *c;
       int i;

       /* find the encoder */
       *codec = avcodec_find_encoder(codec_id);
       if (!(*codec)) {
           OutputDebugString(L"Could not find encoder for '%s'\n");
           //avcodec_get_name(codec_id));
           exit(1);
       }

       ost->st = avformat_new_stream(oc, NULL);
       if (!ost->st) {
           OutputDebugString(L"Could not allocate stream\n");
           exit(1);
       }
       ost->st->id = oc->nb_streams - 1;
       c = avcodec_alloc_context3(*codec);
       if (!c) {
           OutputDebugString(L"Could not alloc an encoding context\n");
           exit(1);
       }
       ost->enc = c;

       switch ((*codec)->type) {
       case AVMEDIA_TYPE_AUDIO:
           c->sample_fmt = (*codec)->sample_fmts ?
               (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
           c->bit_rate = 64000;
           c->sample_rate = 44100;
           if ((*codec)->supported_samplerates) {
               c->sample_rate = (*codec)->supported_samplerates[0];
               for (i = 0; (*codec)->supported_samplerates[i]; i++) {
                   if ((*codec)->supported_samplerates[i] == 44100)
                       c->sample_rate = 44100;
               }
           }
           c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
           c->channel_layout = AV_CH_LAYOUT_STEREO;
           if ((*codec)->channel_layouts) {
               c->channel_layout = (*codec)->channel_layouts[0];
               for (i = 0; (*codec)->channel_layouts[i]; i++) {
                   if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO)
                       c->channel_layout = AV_CH_LAYOUT_STEREO;
               }
           }
           c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
           ost->st->time_base = /*(AVRational)*/{ 1, c->sample_rate };
           break;

       case AVMEDIA_TYPE_VIDEO:
           c->codec_id = codec_id;

           c->bit_rate = 400000;
           /* Resolution must be a multiple of two. */
           c->width = 352;
           c->height = 288;
           /* timebase: This is the fundamental unit of time (in seconds) in terms
           * of which frame timestamps are represented. For fixed-fps content,
           * timebase should be 1/framerate and timestamp increments should be
           * identical to 1. */
           ost->st->time_base = /*(AVRational)*/{ 1, STREAM_FRAME_RATE };
           c->time_base = ost->st->time_base;

           c->gop_size = 12; /* emit one intra frame every twelve frames at most */
           c->pix_fmt = STREAM_PIX_FMT;
               if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
                   /* just for testing, we also add B-frames */
                   c->max_b_frames = 2;
               }
               if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
                   /* Needed to avoid using macroblocks in which some coeffs overflow.
                   * This does not happen with normal video, it just happens here as
                   * the motion of the chroma plane does not match the luma plane. */
                   c->mb_decision = 2;
               }
               break;

           default:
               break;
           }

            /* Some formats want stream headers to be separate. */
           if (oc->oformat->flags & AVFMT_GLOBALHEADER)
               c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
       }

    AVFrame * RTMPWriter::alloc_audio_frame(
       enum AVSampleFormat sample_fmt,
       uint64_t channel_layout,
       int sample_rate, int nb_samples)
    {
       AVFrame *frame = av_frame_alloc();
       int ret;

       if (!frame) {
           OutputDebugString(L"Error allocating an audio frame\n");
           exit(1);
       }

       frame->format = sample_fmt;
       frame->channel_layout = channel_layout;
       frame->sample_rate = sample_rate;
       frame->nb_samples = nb_samples;

       if (nb_samples) {
           ret = av_frame_get_buffer(frame, 0);
           if (ret < 0) {
               OutputDebugString(L"Error allocating an audio buffer\n");
               exit(1);
           }
       }

           return frame;
       }




    void  RTMPWriter::open_audio(
       AVFormatContext *oc,
       AVCodec *codec,
       OutputStream *ost,
       AVDictionary *opt_arg)
    {
       AVCodecContext *c;
       int nb_samples;
       int ret;
       AVDictionary *opt = NULL;

       c = ost->enc;

       /* open it */
       av_dict_copy(&opt, opt_arg, 0);
       ret = avcodec_open2(c, codec, &opt);
       av_dict_free(&opt);
       if (ret < 0) {
           OutputDebugString(L"Could not open audio codec: %s\n");// , av_err2str(ret));
           exit(1);
       }

       /* init signal generator */
       ost->t = 0;
       ost->tincr = 2 * M_PI * 110.0 / c->sample_rate;
       /* increment frequency by 110 Hz per second */
       ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;

       if (c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
           nb_samples = 10000;
       else
           nb_samples = c->frame_size;

       ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout,
           c->sample_rate, nb_samples);
       ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout,
           c->sample_rate, nb_samples);

       /* copy the stream parameters to the muxer */
       ret = avcodec_parameters_from_context(ost->st->codecpar, c);
       if (ret < 0) {
           OutputDebugString(L"Could not copy the stream parameters\n");
           exit(1);
       }

       /* create resampler context */
       ost->swr_ctx = swr_alloc();
       if (!ost->swr_ctx) {
           OutputDebugString(L"Could not allocate resampler context\n");
           exit(1);
       }

       /* set options */
       av_opt_set_int(ost->swr_ctx, "in_channel_count", c->channels, 0);
       av_opt_set_int(ost->swr_ctx, "in_sample_rate", c->sample_rate, 0);
       av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
       av_opt_set_int(ost->swr_ctx, "out_channel_count", c->channels, 0);
       av_opt_set_int(ost->swr_ctx, "out_sample_rate", c->sample_rate, 0);
       av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0);

       /* initialize the resampling context */
       if ((ret = swr_init(ost->swr_ctx)) < 0) {
           OutputDebugString(L"Failed to initialize the resampling context\n");
           exit(1);
       }
    }

    int RTMPWriter::write_frame(
       AVFormatContext *fmt_ctx,
       const AVRational *time_base,
       AVStream *st,
       AVPacket *pkt)
    {
       /* rescale output packet timestamp values from codec to stream timebase */
       av_packet_rescale_ts(pkt, *time_base, st->time_base);
       pkt->stream_index = st->index;

       /* Write the compressed frame to the media file. */
       //log_packet(fmt_ctx, pkt);
       OutputDebugString(L"Actually sending video frame: %s\n");
       return av_interleaved_write_frame(fmt_ctx, pkt);
    }


    AVFrame  *RTMPWriter::alloc_picture(
       enum AVPixelFormat pix_fmt,
       int width,
       int height)
    {
       AVFrame *picture;
       int ret;

       picture = av_frame_alloc();
       if (!picture)
           return NULL;

       picture->format = pix_fmt;
       picture->width = width;
       picture->height = height;

       /* allocate the buffers for the frame data */
       ret = av_frame_get_buffer(picture, 32);
       if (ret < 0) {
           fprintf(stderr, "Could not allocate frame data.\n");
           exit(1);
       }

       return picture;
    }

    void RTMPWriter::open_video(
       AVFormatContext *oc,
       AVCodec *codec,
       OutputStream *ost,
       AVDictionary *opt_arg)
    {
       int ret;
       AVCodecContext *c = ost->enc;
       AVDictionary *opt = NULL;

       av_dict_copy(&opt, opt_arg, 0);

       /* open the codec */
       ret = avcodec_open2(c, codec, &opt);
       av_dict_free(&opt);
       if (ret < 0) {
           OutputDebugString(L"Could not open video codec: %s\n");// , av_err2str(ret));
           exit(1);
       }

       /* allocate and init a re-usable frame */
       ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);
       if (!ost->frame) {
           OutputDebugString(L"Could not allocate video frame\n");
           exit(1);
       }

       /* If the output format is not YUV420P, then a temporary YUV420P
       * picture is needed too. It is then converted to the required
       * output format. */
       ost->tmp_frame = NULL;
       if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
           ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);
           if (!ost->tmp_frame) {
               OutputDebugString(L"Could not allocate temporary picture\n");
               exit(1);
           }
       }

       /* copy the stream parameters to the muxer */
       ret = avcodec_parameters_from_context(ost->st->codecpar, c);
       if (ret < 0) {
           OutputDebugString(L"Could not copy the stream parameters\n");
           exit(1);
       }
    }

    void RTMPWriter::close_stream(AVFormatContext *oc, OutputStream *ost)
    {
       avcodec_free_context(&ost->enc);
       av_frame_free(&ost->frame);
       av_frame_free(&ost->tmp_frame);
       sws_freeContext(ost->sws_ctx);
       swr_free(&ost->swr_ctx);
    }

    RTMPWriter::~RTMPWriter()
    {
       av_write_trailer(oc);
       /* Close each codec. */
       if (have_video)
           close_stream(oc, &video_st);
       if (have_audio)
           close_stream(oc, &audio_st);

       if (!(fmt->flags & AVFMT_NOFILE))
           /* Close the output file. */
           avio_closep(&oc->pb);

       /* free the stream */
       avformat_free_context(oc);
    }