* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#define LOG_NDEBUG 0
#define LOG_TAG "FFMPEG"
#include <utils/Log.h>
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/avassert.h"
-#include "libavutil/intreadwrite.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavcodec/avfft.h"
#include "libswresample/swresample.h"
-#include "cmdutils.h"
-
#undef strncpy
#include <string.h>
}
#endif
+#include <cutils/properties.h>
+
+#include "ffmpeg_utils.h"
+#include "ffmpeg_source.h"
+
// log
static int flags;
const int program_birth_year = 2012;
// init ffmpeg
-static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
-static int ref_count = 0;
+static pthread_mutex_t s_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int s_ref_count = 0;
namespace android {
extern "C" {
#endif
-void av_noreturn exit_program(int ret)
+void exit_program(int ret)
{
// do nothing
}
}
}
+// TODO, remove static variables to support multi-instances
void nam_av_log_callback(void* ptr, int level, const char* fmt, va_list vl)
{
static int print_prefix = 1;
return;
}
if (count > 0) {
- LOGI("Last message repeated %d times\n", count);
+ ALOGI("Last message repeated %d times\n", count);
count = 0;
}
strcpy(prev, line);
sanitize((uint8_t *)line);
#if 0
- LOGI("%s", line);
+ ALOGI("%s", line);
#else
#define LOG_BUF_SIZE 1024
static char g_msg[LOG_BUF_SIZE];
g_msg_len += 1;
g_msg[g_msg_len] = '\n';
}
- LOGI("%s", g_msg);
+ ALOGI("%s", g_msg);
/* reset g_msg and g_msg_len */
memset(g_msg, 0, LOG_BUF_SIZE);
g_msg_len = 0;
return 1;
}
+/**
+ * To debug ffmpeg", type this command on the console before starting playback:
+ * setprop debug.nam.ffmpeg 1
+ * To disable the debug, type:
+ * setprop debug.nam.ffmpge 0
+*/
status_t initFFmpeg()
{
status_t ret = OK;
+ bool debug_enabled = false;
+ char value[PROPERTY_VALUE_MAX];
+
+ pthread_mutex_lock(&s_init_mutex);
- pthread_mutex_lock(&init_mutex);
+ if (property_get("debug.nam.ffmpeg", value, NULL)
+ && (!strcmp(value, "1") || !av_strcasecmp(value, "true"))) {
+ ALOGI("set ffmpeg debug level to AV_LOG_DEBUG");
+ debug_enabled = true;
+ }
+ if (debug_enabled)
+ av_log_set_level(AV_LOG_DEBUG);
+ else
+ av_log_set_level(AV_LOG_INFO);
- if(ref_count == 0) {
+ if(s_ref_count == 0) {
nam_av_log_set_flags(AV_LOG_SKIP_REPEATED);
- //av_log_set_level(AV_LOG_DEBUG);
av_log_set_callback(nam_av_log_callback);
/* register all codecs, demux and protocols */
av_register_all();
avformat_network_init();
- init_opts();
+ /* register android source */
+ ffmpeg_register_android_source();
if (av_lockmgr_register(lockmgr)) {
- LOGE("could not initialize lock manager!");
+ ALOGE("could not initialize lock manager!");
ret = NO_INIT;
}
}
// update counter
- ref_count++;
+ s_ref_count++;
- pthread_mutex_unlock(&init_mutex);
+ pthread_mutex_unlock(&s_init_mutex);
return ret;
}
void deInitFFmpeg()
{
- pthread_mutex_lock(&init_mutex);
+ pthread_mutex_lock(&s_init_mutex);
// update counter
- ref_count--;
+ s_ref_count--;
- if(ref_count == 0) {
+ if(s_ref_count == 0) {
av_lockmgr_register(NULL);
- uninit_opts();
avformat_network_deinit();
}
- pthread_mutex_unlock(&init_mutex);
+ pthread_mutex_unlock(&s_init_mutex);
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/* H.264 bitstream with start codes, NOT AVC1! ref: libavcodec/h264_parser.c */
static int h264_split(AVCodecContext *avctx,
- const uint8_t *buf, int buf_size, int check_compatible_only)
+ const uint8_t *buf, int buf_size, int check_compatible_only)
{
int i;
uint32_t state = -1;
for(i=0; i<=buf_size; i++){
if((state&0xFFFFFF1F) == 0x107) {
- LOGI("found NAL_SPS");
+ ALOGI("found NAL_SPS");
has_sps=1;
}
if((state&0xFFFFFF1F) == 0x108) {
- LOGI("found NAL_PPS");
+ ALOGI("found NAL_PPS");
has_pps=1;
if (check_compatible_only)
return (has_sps & has_pps);
}
- if((state&0xFFFFFF00) == 0x100 && ((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105)){
+ if((state&0xFFFFFF00) == 0x100
+ && ((state&0xFFFFFF1F) == 0x101
+ || (state&0xFFFFFF1F) == 0x102
+ || (state&0xFFFFFF1F) == 0x105)){
if(has_pps){
while(i>4 && buf[i-5]==0) i--;
return i-4;
/* ref: libavcodec/mpegvideo_parser.c */
static int mpegvideo_split(AVCodecContext *avctx,
- const uint8_t *buf, int buf_size, int check_compatible_only)
+ const uint8_t *buf, int buf_size, int check_compatible_only)
{
int i;
uint32_t state= -1;
/* split extradata from buf for Android OMXCodec */
int parser_split(AVCodecContext *avctx,
- const uint8_t *buf, int buf_size)
+ const uint8_t *buf, int buf_size)
{
if (!avctx || !buf || buf_size <= 0) {
- LOGE("parser split, valid params");
+ ALOGE("parser split, valid params");
return 0;
}
- if (avctx->codec_id == CODEC_ID_H264) {
+ if (avctx->codec_id == AV_CODEC_ID_H264) {
return h264_split(avctx, buf, buf_size, 0);
- } else if (avctx->codec_id == CODEC_ID_MPEG2VIDEO ||
- avctx->codec_id == CODEC_ID_MPEG4) {
+ } else if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
+ avctx->codec_id == AV_CODEC_ID_MPEG4) {
return mpegvideo_split(avctx, buf, buf_size, 0);
} else {
- LOGE("parser split, unsupport the codec, id: 0x%0x", avctx->codec_id);
+ ALOGE("parser split, unsupport the codec, id: 0x%0x", avctx->codec_id);
}
return 0;
int is_extradata_compatible_with_android(AVCodecContext *avctx)
{
if (avctx->extradata_size <= 0) {
- LOGI("extradata_size <= 0, extradata is not compatible with android decoder, the codec id: 0x%0x", avctx->codec_id);
+ ALOGI("extradata_size <= 0, extradata is not compatible with "
+ "android decoder, the codec id: 0x%0x", avctx->codec_id);
return 0;
}
- if (avctx->codec_id == CODEC_ID_H264 && avctx->extradata[0] != 1 /* configurationVersion */) {
+ if (avctx->codec_id == AV_CODEC_ID_H264
+ && avctx->extradata[0] != 1 /* configurationVersion */) {
// SPS + PPS
- return !!(h264_split(avctx, avctx->extradata, avctx->extradata_size, 1) > 0);
+ return !!(h264_split(avctx, avctx->extradata,
+ avctx->extradata_size, 1) > 0);
} else {
// default, FIXME
return !!(avctx->extradata_size > 0);