The problem appears to be that guess_format(NULL, "somefilename.mp2",
NULL) returns an AVOutputFormat whose name is "mp2" but whose
video_codec is NULL.

I guess I need to persuade it to be mp2video, or similar.

2009/6/22 Ricky Clarkson <[email protected]>:
> I've now got to the same point in C that I was in Java - no segfault,
> just an unplayable file.
>
> The code (rewritten; basically dranger's tutorial and output_example.c 
> merged):
>
> #include "avcodec.h"
> #include "avformat.h"
> #include "imgconvert.h"
> #include "stdio.h"
> #include "libswscale/swscale.h"
>
> #define STREAM_DURATION 5.0
>
> /* add a video output stream */
> static AVStream *add_video_stream(AVFormatContext *oc, int codec_id)
> {
>    AVCodecContext *c;
>    AVStream *st;
>
>    st = av_new_stream(oc, 0);
>    if (!st) {
>        fprintf(stderr, "Could not alloc stream\n");
>        exit(1);
>    }
>
>    c = st->codec;
>    c->codec_id = codec_id;
>    c->codec_type = CODEC_TYPE_VIDEO;
>
>    /* put sample parameters */
>    c->bit_rate = 400000;
>    /* resolution must be a multiple of two */
>    c->width = 352;
>    c->height = 288;
>    /* time base: 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
>       identically 1. */
>    c->time_base.den = 25;
>    c->time_base.num = 1;
>    c->gop_size = 12; /* emit one intra frame every twelve frames at most */
>    c->pix_fmt = PIX_FMT_YUV420P;
>    if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
>        /* just for testing, we also add B frames */
>        c->max_b_frames = 2;
>    }
>    if (c->codec_id == 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;
>    }
>    // some formats want stream headers to be separate
>    if(oc->oformat->flags & AVFMT_GLOBALHEADER)
>        c->flags |= CODEC_FLAG_GLOBAL_HEADER;
>
>    return st;
> }
>
> AVFrame *picture, *tmp_picture;
> uint8_t *video_outbuf;
> int video_outbuf_size;
>
> static AVFrame *alloc_picture(int pix_fmt, int width, int height)
> {
>    AVFrame *picture;
>    uint8_t *picture_buf;
>    int size;
>
>    picture = avcodec_alloc_frame();
>    if (!picture)
>        return NULL;
>    size = avpicture_get_size(pix_fmt, width, height);
>    picture_buf = av_malloc(size);
>    if (!picture_buf) {
>        av_free(picture);
>        return NULL;
>    }
>    avpicture_fill((AVPicture *)picture, picture_buf,
>                   pix_fmt, width, height);
>    return picture;
> }
>
> static void open_video(AVFormatContext *oc, AVStream *st)
> {
>    AVCodec *codec;
>    AVCodecContext *c;
>
>    c = st->codec;
>
>    /* find the video encoder */
>    codec = avcodec_find_encoder(c->codec_id);
>    if (!codec) {
>        fprintf(stderr, "codec not found\n");
>        exit(1);
>    }
>
>    /* open the codec */
>    if (avcodec_open(c, codec) < 0) {
>        fprintf(stderr, "could not open codec\n");
>        exit(1);
>    }
>
>    video_outbuf = NULL;
>    if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
>        /* allocate output buffer */
>        /* XXX: API change will be done */
>        /* buffers passed into lav* can be allocated any way you prefer,
>           as long as they're aligned enough for the architecture, and
>           they're freed appropriately (such as using av_free for buffers
>           allocated with av_malloc) */
>        video_outbuf_size = 200000;
>        video_outbuf = av_malloc(video_outbuf_size);
>    }
>
>    /* allocate the encoded raw picture */
>    picture = alloc_picture(c->pix_fmt, c->width, c->height);
>    if (!picture) {
>        fprintf(stderr, "Could not allocate picture\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 */
>    tmp_picture = NULL;
>    if (c->pix_fmt != PIX_FMT_YUV420P) {
>        tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
>        if (!tmp_picture) {
>            fprintf(stderr, "Could not allocate temporary picture\n");
>            exit(1);
>        }
>    }
> }
>
> int main(int argc, char *argv[]) {
>    AVFormatContext *pFormatCtx;
>    int             i, videoStream;
>    AVCodecContext  *pCodecCtx;
>    AVCodec         *pCodec;
>    AVFrame         *pFrame;
>    AVFrame         *pFrameRGB;
>    AVPacket        packet;
>    int             frameFinished;
>    int             numBytes;
>    uint8_t         *buffer;
>
>    if(argc < 3) {
>        printf("Usage error.\n");
>        return -1;
>    }
>    // Register all formats and codecs
>    av_register_all();
>
>    // Open video file
>    if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
>        return -1; // Couldn't open file
>
>    // Retrieve stream information
>    if(av_find_stream_info(pFormatCtx)<0)
>        return -1; // Couldn't find stream information
>
>    // Dump information about file onto standard error
>    dump_format(pFormatCtx, 0, argv[1], 0);
>
>    // Find the first video stream
>    videoStream=-1;
>    for(i=0; i<pFormatCtx->nb_streams; i++)
>        if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
>            videoStream=i;
>            break;
>        }
>    if(videoStream==-1)
>        return -1; // Didn't find a video stream
>
>    // Get a pointer to the codec context for the video stream
>    pCodecCtx=pFormatCtx->streams[videoStream]->codec;
>
>    // Find the decoder for the video stream
>    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
>    if(pCodec==NULL) {
>        fprintf(stderr, "Unsupported codec!\n");
>        return -1; // Codec not found
>    }
>    // Open codec
>    if(avcodec_open(pCodecCtx, pCodec)<0)
>        return -1; // Could not open codec
>
>    // Allocate video frame
>    pFrame=avcodec_alloc_frame();
>
>    // Allocate an AVFrame structure
>    pFrameRGB=avcodec_alloc_frame();
>    if(pFrameRGB==NULL)
>        return -1;
>
>    // Determine required buffer size and allocate buffer
>    numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
>                                pCodecCtx->height);
>    buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
>
>    // Assign appropriate parts of buffer to image planes in pFrameRGB
>    // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
>    // of AVPicture
>    avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
>                   pCodecCtx->width, pCodecCtx->height);
>
>    AVOutputFormat *fmt = guess_format(NULL, argv[2], NULL);
>    if (!fmt)
>    {
>        return -1;
>    }
>
>    AVFormatContext *oc = av_alloc_format_context();
>    if (!oc)
>    {
>        return -1;
>    }
>
>    oc->oformat = fmt;
>    snprintf(oc->filename, sizeof(oc->filename), "%s", argv[2]);
>
>    AVStream *video_st = NULL;
>    double video_pts;
>
>    if (fmt->video_codec != CODEC_ID_NONE) {
>        video_st = add_video_stream(oc, fmt->video_codec);
>    }
>
>    /* set the output parameters (must be done even if no
>       parameters). */
>    if (av_set_parameters(oc, NULL) < 0) {
>        fprintf(stderr, "Invalid output format parameters\n");
>        exit(1);
>    }
>
>    dump_format(oc, 0, argv[2], 1);
>
>    /* now that all the parameters are set, we can open the audio and
>       video codecs and allocate the necessary encode buffers */
>    if (video_st)
>        open_video(oc, video_st);
>
>    /* open the output file, if needed */
>    if (!(fmt->flags & AVFMT_NOFILE)) {
>        if (url_fopen(&oc->pb, argv[2], URL_WRONLY) < 0) {
>            fprintf(stderr, "Could not open '%s'\n", argv[2]);
>            exit(1);
>        }
>    }
>
>    av_write_header(oc);
>
>    static struct SwsContext *img_convert_ctx;
>
>    // Read frames and save first five frames to disk
>    i=0;
>    int frame_count = 0;
>    while(av_read_frame(pFormatCtx, &packet)>=0) {
>        // Is this a packet from the video stream?
>        if(packet.stream_index==videoStream) {
>            // Decode video frame
>            avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
>                                 packet.data, packet.size);
>
>            // Did we get a video frame?
>            if(frameFinished) {
>                // Convert the image from its native format to RGB
>                img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,
>                            (AVPicture*)pFrame, pCodecCtx->pix_fmt,
> pCodecCtx->width,
>                            pCodecCtx->height);
>
>                // Save the frame to disk
>                if (video_st)
>                    video_pts = (double)video_st->pts.val *
> video_st->time_base.num / video_st->time_base.den;
>                else
>                    video_pts = 0.0;
>
>                if (!video_st || video_pts >= STREAM_DURATION)
>                    break;
>
>                AVCodecContext *c = video_st->codec;
>                if (c->pix_fmt != PIX_FMT_YUV420P) {
>                    if (img_convert_ctx == NULL) {
>                        img_convert_ctx = sws_getContext(c->width, c->height,
>                                                         PIX_FMT_YUV420P,
>                                                         c->width, c->height,
>                                                         c->pix_fmt,
>                                                         SWS_BICUBIC,
> NULL, NULL, NULL);
>                        if (img_convert_ctx == NULL)
>                            return -1;
>                    }
>                    int out_size = avcodec_encode_video(c,
> video_outbuf, video_outbuf_size, pFrameRGB);
>                    AVPacket pkt;
>                    av_init_packet(&pkt);
>
>                    if (c->coded_frame->pts != AV_NOPTS_VALUE)
>                        pkt.pts=av_rescale_q(c->coded_frame->pts,
> c->time_base, video_st->time_base);
>                    if (c->coded_frame->key_frame)
>                        pkt.flags |= PKT_FLAG_KEY;
>                    pkt.stream_index = video_st->index;
>                    pkt.data = video_outbuf;
>                    pkt.size = out_size;
>
>                    if (av_interleaved_write_frame(oc, &pkt) != 0)
>                        return -1;
>                }
>            }
>        }
>
>        // Free the packet that was allocated by av_read_frame
>        av_free_packet(&packet);
>    }
>
>    av_free(buffer);
>    av_free(pFrameRGB);
>    av_free(pFrame);
>    avcodec_close(pCodecCtx);
>    av_close_input_file(pFormatCtx);
>
>    return 0;
> }
>
> The output:
>
> test.c: In function ‘main’:
> test.c:209: warning: ‘av_alloc_format_context’ is deprecated (declared
> at /home/ricky/ffmpeg/libavformat/avformat.h:873)
> Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/ricky/cavity_flow_movie.mp4':
>  Duration: 00:00:41.66, start: 0.000000, bitrate: 2301 kb/s
>    Stream #0.0(eng): Video: mpeg4, yuv420p, 320x240 [PAR 1:1 DAR
> 4:3], 30.00 tb(r)
>    Stream #0.1(eng): Data: mp4s / 0x7334706D
>    Stream #0.2(eng): Data: mp4s / 0x7334706D
> Output #0, mp2, to '/home/ricky/cavity_flow_movie.mp2':
>
> The problem:
>
> ri...@ricky-desktop:~/ffmpegplay$ ffplay ~/cavity_flow_movie.mp2
> FFplay version 0.5-svn17737+3:0.svn20090303-1ubuntu6, Copyright (c)
> 2003-2009 Fabrice Bellard, et al.
>  configuration: --enable-gpl --enable-postproc --enable-swscale
> --enable-x11grab --extra-version=svn17737+3:0.svn20090303-1ubuntu6
> --prefix=/usr --enable-avfilter --enable-avfilter-lavf --enable-libgsm
> --enable-libschroedinger --enable-libspeex --enable-libtheora
> --enable-libvorbis --enable-pthreads --disable-stripping
> --disable-vhook --enable-libdc1394 --disable-armv5te --disable-armv6
> --disable-armv6t2 --disable-armvfp --disable-neon --disable-altivec
> --disable-vis --enable-shared --disable-static
>  libavutil     49.15. 0 / 49.15. 0
>  libavcodec    52.20. 0 / 52.20. 0
>  libavformat   52.31. 0 / 52.31. 0
>  libavdevice   52. 1. 0 / 52. 1. 0
>  libavfilter    0. 4. 0 /  0. 4. 0
>  libswscale     0. 7. 1 /  0. 7. 1
>  libpostproc   51. 2. 0 / 51. 2. 0
>  built on Apr 10 2009 23:18:41, gcc: 4.3.3
> /home/ricky/cavity_flow_movie.mp2: Unknown format
>
> Any suggestions?
>
> 2009/6/22 Art Clarke <[email protected]>:
>> On Mon, Jun 22, 2009 at 6:54 AM, Ricky Clarkson 
>> <[email protected]>wrote:
>>
>>> I already have some Java code that converts our in-memory streams to
>>> AVI files, and was originally hoping to adapt that.  I did so, but
>>> found the results unplayable (ffmpeg -i theoutput.mp2 reports 'Unknown
>>> format').  I already noticed xuggle and was planning to look into it
>>> further.  Is it as straightforward to use from a 'programmatic' data
>>> source as it is directly from files?
>>>
>>
>> I suggest joining the http://groups.google.com/group/xuggler-users group for
>> detailed questions, but we allow you to use files, InputStreams,
>> OutputStreams, ReadableByteChannels, WritableByteChannels, DataInput,
>> DataOutput and RandomAccessFile objects.  Or if none of those work, you can
>> do a custom IO handler by implementing the IURLProtocolHandler interface in
>> Xuggler and opening that.
>>
>> - Art
>>
>> --
>> http://www.xuggle.com/
>> xu‧ggle (zŭ' gl) v. To freely encode, decode, and experience audio and
>> video.
>>
>> Use Xuggle to get the power of FFMPEG in Java.
>> _______________________________________________
>> libav-user mailing list
>> [email protected]
>> https://lists.mplayerhq.hu/mailman/listinfo/libav-user
>>
>
>
>
> --
> Ricky Clarkson
> Java Programmer, AD Holdings
> +44 1565 770804
> Skype: ricky_clarkson
> Google Talk: [email protected]
>



-- 
Ricky Clarkson
Java Programmer, AD Holdings
+44 1565 770804
Skype: ricky_clarkson
Google Talk: [email protected]
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to