2 //metadoc AVCodec copyright Steve Dekorte, 2004
3 //metadoc AVCodec license BSD revised
4 //metadoc AVCodec category Media
5 /*metadoc AVCodec description
6 An object for encoding and decoding audio and video streams.
19 #define DATA(self) ((IoAVCodecData *)IoObject_dataPointer(self))
21 void IoAVCodec_registerIfNeeded(IoAVCodec
*self
)
24 avcodec_register_all();
28 IoTag
*IoAVCodec_newTag(void *state
)
30 IoTag
*tag
= IoTag_newWithName_("AVCodec");
31 IoTag_state_(tag
, state
);
32 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoAVCodec_rawClone
);
33 IoTag_markFunc_(tag
, (IoTagMarkFunc
*)IoAVCodec_mark
);
34 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoAVCodec_free
);
38 IoAVCodec
*IoAVCodec_proto(void *state
)
40 IoObject
*self
= IoObject_new(state
);
41 IoObject_tag_(self
, IoAVCodec_newTag(state
));
43 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoAVCodecData
)));
45 DATA(self
)->inputBuffer
= IoSeq_new(state
);
46 DATA(self
)->outputBuffer
= IoSeq_new(state
);
48 IoState_registerProtoWithFunc_(state
, self
, IoAVCodec_proto
);
50 IoAVCodec_registerIfNeeded(self
);
53 IoMethodTable methodTable
[] = {
55 {"audioInputBuffer", IoAVCodec_audioInputBuffer
},
56 {"audioOutputBuffer", IoAVCodec_audioOutputBuffer
},
58 {"encodeCodecNames", IoAVCodec_encodeCodecNames
},
59 {"decodeCodecNames", IoAVCodec_decodeCodecNames
},
61 {"open", IoAVCodec_open
},
62 {"close", IoAVCodec_close
},
64 {"decode", IoAVCodec_decode
},
65 {"isAtEnd", IoAVCodec_isAtEnd
},
66 //{"encode", IoAVCodec_startEncoding},
70 IoObject_addMethodTable_(self
, methodTable
);
75 IoAVCodec
*IoAVCodec_rawClone(IoAVCodec
*proto
)
77 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
78 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoAVCodecData
)));
80 DATA(self
)->inputBuffer
= IOCLONE(DATA(proto
)->inputBuffer
);
81 DATA(self
)->outputBuffer
= IOCLONE(DATA(proto
)->outputBuffer
);
86 IoAVCodec
*IoAVCodec_new(void *state
)
88 IoObject
*proto
= IoState_protoWithInitFunction_(state
, IoAVCodec_proto
);
89 return IOCLONE(proto
);
92 // -----------------------------------------------------------
94 void IoAVCodec_createContextIfNeeded(IoAVCodec
*self
)
96 if(!DATA(self
)->packet
)
98 DATA(self
)->packet
= calloc(1, sizeof(AVPacket
));
104 if (!DATA(self
)->frames
)
106 DATA(self
)->frames
= IoList_new(IOSTATE
);
107 IoObject_setSlot_to_(self
, IOSYMBOL("frames"), DATA(self
)->frames
);
112 UArray
*sizeUArray
= UArray_newWithData_type_encoding_size_copy_("", CTYPE_float32_t
, CENCODING_NUMBER
, 2, 1);
113 IoSeq
*sizeSeq
= IoSeq_newWithUArray_copy_(IOSTATE
, sizeUArray
, 0);
114 IoObject_setSlot_to_(self
, IOSYMBOL("videoSize"), sizeSeq
);
117 if (!DATA(self
)->decodedFrame
)
119 DATA(self
)->decodedFrame
= avcodec_alloc_frame();
124 if(!DATA(self
)->audioOutBuffer
)
126 DATA(self
)->audioOutBuffer
= malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE
);
130 AVPicture
*IoAVCode_allocDstPictureIfNeeded(IoAVCodec
*self
, int pix_fmt
, int width
, int height
)
132 if(!DATA(self
)->rgbPicture
)
134 DATA(self
)->rgbPicture
= calloc(1, sizeof(AVPicture
));
135 avpicture_alloc(DATA(self
)->rgbPicture
, PIX_FMT_RGB24
, width
, height
);
138 return DATA(self
)->rgbPicture
;
142 void IoAVCodec_freeContextIfNeeded(IoAVCodec
*self
)
144 //printf("IoAVCodec_freeContextIfNeeded\n");
146 DATA(self
)->audioContext
= NULL
;
147 DATA(self
)->videoContext
= NULL
;
149 if (DATA(self
)->audioContext
)
151 //avcodec_close(DATA(self)->audioContext);
152 //av_free(DATA(self)->audioContext);
153 DATA(self
)->audioContext
= NULL
;
156 if (DATA(self
)->videoContext
)
158 //avcodec_close(DATA(self)->audioContext);
159 //av_free(DATA(self)->audioContext);
160 DATA(self
)->audioContext
= NULL
;
163 if (DATA(self
)->formatContext
)
165 av_close_input_file(DATA(self
)->formatContext
);
166 //av_free(DATA(self)->formatContext);
167 DATA(self
)->formatContext
= NULL
;
170 if(DATA(self
)->packet
)
172 //free(DATA(self)->packet);
173 DATA(self
)->packet
= NULL
;
176 if (DATA(self
)->audioOutBuffer
)
178 //free(DATA(self)->audioOutBuffer);
179 DATA(self
)->audioOutBuffer
= NULL
;
182 if(DATA(self
)->decodedFrame
)
184 //av_free(DATA(self)->decodedFrame);
185 DATA(self
)->decodedFrame
= NULL
;
188 if(DATA(self
)->rgbPicture
)
190 avpicture_free(DATA(self
)->rgbPicture
);
191 //free(DATA(self)->rgbPicture);
192 DATA(self
)->rgbPicture
= NULL
;
195 //printf("IoAVCodec_freeContextIfNeeded done\n");
198 void IoAVCodec_free(IoAVCodec
*self
)
200 IoAVCodec_freeContextIfNeeded(self
);
201 free(IoObject_dataPointer(self
));
204 void IoAVCodec_mark(IoAVCodec
*self
)
206 if(DATA(self
)->frames
) IoObject_shouldMark(DATA(self
)->frames
);
208 IoObject_shouldMark(DATA(self
)->inputBuffer
);
209 IoObject_shouldMark(DATA(self
)->outputBuffer
);
212 // -----------------------------------------------------------
214 void IoAVCodec_error_(IoAVCodec
*self
, IoMessage
*m
, char *s
)
217 IoState_error_(IOSTATE
, m
, s
);
220 IoObject
*IoAVCodec_audioInputBuffer(IoAVCodec
*self
, IoObject
*locals
, IoMessage
*m
)
222 /*doc AVCodec inputBuffer
223 Returns the input buffer.
225 return DATA(self
)->inputBuffer
;
228 IoObject
*IoAVCodec_audioOutputBuffer(IoAVCodec
*self
, IoObject
*locals
, IoMessage
*m
)
230 /*doc AVCodec outputBuffer
231 Returns the output buffer.
233 return DATA(self
)->outputBuffer
;
236 IoObject
*IoAVCodec_decodeCodecNames(IoAVCodec
*self
, IoObject
*locals
, IoMessage
*m
)
238 /*doc AVCodec decodeCodecNames
239 Returns a list of strings with the names of the decode codecs.
242 AVCodec
*p
= first_avcodec
;
243 IoList
*names
= IoList_new(IOSTATE
);
249 IoList_rawAppend_(names
, IOSYMBOL(p
->name
));
258 IoObject
*IoAVCodec_encodeCodecNames(IoAVCodec
*self
, IoObject
*locals
, IoMessage
*m
)
260 /*doc AVCodec encodeCodecNames
261 Returns a list of strings with the names of the encode codecs.
264 AVCodec
*p
= first_avcodec
;
265 IoList
*names
= IoList_new(IOSTATE
);
271 IoList_rawAppend_(names
, IOSYMBOL(p
->name
));
280 void IoAVCodec_ConvertShortToFloat(short *s
, float *f
, size_t sampleCount
)
284 for (i
= 0; i
< sampleCount
; i
++)
286 *f
= (float)(*s
) / (float)SHRT_MAX
;
288 *f
= (float)(*s
) / (float)SHRT_MAX
;
293 void IoAVCodec_ConvertFloatToShort(float *f
, short *s
, size_t sampleCount
)
297 for (i
= 0; i
< sampleCount
; i
++)
299 *s
= (short)((*f
) * SHRT_MAX
);
301 *s
= (short)((*f
) * SHRT_MAX
);
306 // -----------------------------------------------------------
308 #define INBUF_SIZE 4096
310 // ----------------------------------------------------------------------------------------------
312 IoObject
*IoAVCodec_close(IoAVCodec
*self
, IoObject
*locals
, IoMessage
*m
)
314 IoAVCodec_registerIfNeeded(self
);
315 IoAVCodec_freeContextIfNeeded(self
);
319 int IoAVCodec_openFile(IoAVCodec
*self
)
321 //AVInputFormat *inputFormat;
322 IoObject
*fileName
= IoObject_symbolGetSlot_(self
, IOSYMBOL("path"));
323 int err
= av_open_input_file(&DATA(self
)->formatContext
, CSTRING(fileName
), NULL
, 0, NULL
);
327 IoObject
*IoAVCodec_open(IoAVCodec
*self
, IoObject
*locals
, IoMessage
*m
)
331 IoAVCodec_registerIfNeeded(self
);
332 IoAVCodec_freeContextIfNeeded(self
);
333 IoAVCodec_createContextIfNeeded(self
);
335 DATA(self
)->isAtEnd
= 0;
337 err
= IoAVCodec_openFile(self
);
341 IoObject
*fileName
= IoObject_symbolGetSlot_(self
, IOSYMBOL("path"));
342 IoState_error_(IOSTATE
, m
, "error %i opening file %s\n", err
, CSTRING(fileName
));
346 IoAVCodec_findStreams(self
);
347 av_read_play(DATA(self
)->formatContext
);
352 int IoAVCodec_findStreams(IoAVCodec
*self
)
354 AVFormatContext
*formatContext
= DATA(self
)->formatContext
;
357 av_find_stream_info(formatContext
);
359 //printf("formatContext = %p streams = %i\n", (void *)formatContext, formatContext->nb_streams);
361 for(i
= 0; i
< formatContext
->nb_streams
; i
++)
363 AVStream
*stream
= formatContext
->streams
[i
];
364 AVCodecContext
*codecContext
= stream
->codec
;
366 switch(codecContext
->codec_type
)
368 case CODEC_TYPE_AUDIO
:
369 DATA(self
)->audioStreamIndex
= i
;
371 AVCodec
*codec
= avcodec_find_decoder(codecContext
->codec_id
);
375 int err
= avcodec_open(codecContext
, codec
);
379 DATA(self
)->audioContext
= codecContext
;
384 //printf("audioStreamIndex = %i\n", DATA(self)->audioStreamIndex);
385 IoObject_setSlot_to_(self
, IOSYMBOL("audioChannels"), IONUMBER(codecContext
->channels
));
386 IoObject_setSlot_to_(self
, IOSYMBOL("audioSampleRate"), IONUMBER(codecContext
->sample_rate
));
387 IoObject_setSlot_to_(self
, IOSYMBOL("audioBitRate"), IONUMBER(codecContext
->bit_rate
));
388 IoObject_setSlot_to_(self
, IOSYMBOL("audioDuration"), IONUMBER(stream
->duration
));
389 IoObject_setSlot_to_(self
, IOSYMBOL("audioFrameCount"), IONUMBER(stream
->nb_frames
));
392 case CODEC_TYPE_VIDEO
:
394 DATA(self
)->videoStreamIndex
= i
;
397 AVCodec
*codec
= avcodec_find_decoder(codecContext
->codec_id
);
401 int err
= avcodec_open(codecContext
, codec
);
405 DATA(self
)->videoContext
= codecContext
;
410 //printf("videoStreamIndex = %i\n", DATA(self)->videoStreamIndex);
412 float framePeriod
= (((float)codecContext
->time_base
.num
)/((float)codecContext
->time_base
.den
));
413 //UArray *sizeUArray = UArray_newWithData_type_encoding_size_copy_("", CTYPE_float32_t, CENCODING_NUMBER, 2, 1);
414 IoObject_setSlot_to_(self
, IOSYMBOL("framePeriod"), IONUMBER(framePeriod
));
415 IoObject_setSlot_to_(self
, IOSYMBOL("videoDuration"), IONUMBER(stream
->duration
));
416 IoObject_setSlot_to_(self
, IOSYMBOL("videoFrameCount"), IONUMBER(stream
->nb_frames
));
420 UArray
*sizeUArray
= UArray_newWithData_type_encoding_size_copy_("", CTYPE_float32_t
, CENCODING_NUMBER
, 2, 1);
421 IoSeq
*sizeSeq
= IoSeq_newWithUArray_copy_(IOSTATE
, sizeUArray
, 0);
422 UArray_at_putDouble_(sizeUArray
, 0, codecContext
->width
);
423 UArray_at_putDouble_(sizeUArray
, 1, codecContext
->height
);
424 IoObject_setSlot_to_(self
, IOSYMBOL("videoSize"), sizeSeq
);
429 case CODEC_TYPE_UNKNOWN
:
430 case CODEC_TYPE_DATA
:
431 case CODEC_TYPE_SUBTITLE
:
440 IoObject
*IoAVCodec_isAtEnd(IoAVCodec
*self
, IoObject
*locals
, IoMessage
*m
)
442 return IOBOOL(self
, DATA(self
)->isAtEnd
);
445 IoObject
*IoAVCodec_decode(IoAVCodec
*self
, IoObject
*locals
, IoMessage
*m
)
447 AVFormatContext
*formatContext
= DATA(self
)->formatContext
;
448 int audioStreamIndex
= DATA(self
)->audioStreamIndex
;
449 int videoStreamIndex
= DATA(self
)->videoStreamIndex
;
450 AVPacket
*packet
= DATA(self
)->packet
;
454 if(DATA(self
)->audioContext
== NULL
&& DATA(self
)->videoContext
== NULL
)
456 //printf("not open\n");
460 ret
= av_read_frame(formatContext
, packet
);
464 //printf("av_read_frame ret = %i\n", ret);
466 if(ret
== AVERROR_IO
)
468 DATA(self
)->isAtEnd
= 1;
474 if (packet
->stream_index
== audioStreamIndex
&& DATA(self
)->audioContext
)
476 IoAVCodec_decodeAudioPacket(self
,
477 formatContext
->streams
[audioStreamIndex
]->codec
,
478 packet
->data
, packet
->size
);
480 else if (packet
->stream_index
== videoStreamIndex
&& DATA(self
)->videoContext
)
482 IoAVCodec_decodeVideoPacket(self
,
483 formatContext
->streams
[videoStreamIndex
]->codec
,
484 packet
->data
, packet
->size
);
488 av_free_packet(packet
);
494 int IoAVCodec_decodeAudioPacket(IoAVCodec
*self
, AVCodecContext
*c
, uint8_t *inbuf
, size_t size
)
496 UArray
*outba
= IoSeq_rawUArray(DATA(self
)->outputBuffer
);
497 uint8_t *outbuf
= DATA(self
)->audioOutBuffer
;
499 //UArray_setItemType_(outba, CTYPE_float32_t);
504 int len
= avcodec_decode_audio(c
, (int16_t *)outbuf
, &outSize
, inbuf
, size
);
508 printf("Error while decoding audio packet\n");
514 // if a frame has been decoded, output it
515 // convert short ints to floats
517 size_t sampleCount
= outSize
/ c
->channels
;
518 size_t oldSize
= UArray_size(outba
);
519 //UArray_setSize_(outba, oldSize + sampleCount); // knows it's a float32 array
520 UArray_setSize_(outba
, oldSize
+ sampleCount
* sizeof(float)); // knows it's a float32 array
522 IoAVCodec_ConvertShortToFloat((short *)outbuf
, (float *)(UArray_bytes(outba
) + oldSize
), sampleCount
);
532 int IoAVCodec_decodeVideoPacket(IoAVCodec
*self
, AVCodecContext
*c
, uint8_t *inbuf
, size_t size
)
534 AVFrame
*decodeFrame
= DATA(self
)->decodedFrame
;
539 size_t len
= avcodec_decode_video(c
, DATA(self
)->decodedFrame
, &got_picture
, inbuf
, size
);
543 printf("Error while decoding video packet\n");
549 IoList_rawAppend_(DATA(self
)->frames
, IoAVCode_frameSeqForAVFrame_(self
, decodeFrame
, c
->pix_fmt
, c
->width
, c
->height
));
559 IoSeq
*IoAVCode_frameSeqForAVFrame_(IoAVCodec
*self
, AVFrame
*avframe
, int srcPixelFormat
, int width
, int height
)
561 AVPicture
*rgbPicture
= IoAVCode_allocDstPictureIfNeeded(self
, srcPixelFormat
, width
, height
);
562 AVPicture srcPicture
;
565 memcpy(srcPicture
.data
, avframe
->data
, sizeof(uint8_t *) * 4);
566 memcpy(srcPicture
.linesize
, avframe
->linesize
, sizeof(int) * 4);
568 result
= img_convert(rgbPicture
, PIX_FMT_RGB24
, &srcPicture
, srcPixelFormat
, width
, height
);
572 printf("AVCodec: img_convert error?\n");
575 UArray
*data
= UArray_newWithData_type_encoding_size_copy_(rgbPicture
->data
[0], CTYPE_uint8_t
, CENCODING_NUMBER
, width
* height
* 3, 1);
577 return IoSeq_newWithUArray_copy_(IOSTATE
, data
, 0);