mediarecorder.cpp revision b33f3407bab0970a7f9241680723a1140b177c50
1/*
2 **
3 ** Copyright (c) 2008 The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "MediaRecorder"
20#include <utils/Log.h>
21#include <surfaceflinger/Surface.h>
22#include <media/mediarecorder.h>
23#include <binder/IServiceManager.h>
24#include <utils/String8.h>
25#include <media/IMediaPlayerService.h>
26#include <media/IMediaRecorder.h>
27#include <media/mediaplayer.h>  // for MEDIA_ERROR_SERVER_DIED
28#include <gui/ISurfaceTexture.h>
29
30namespace android {
31
32status_t MediaRecorder::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
33{
34    LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
35    if(mMediaRecorder == NULL) {
36        LOGE("media recorder is not initialized yet");
37        return INVALID_OPERATION;
38    }
39    if (!(mCurrentState & MEDIA_RECORDER_IDLE)) {
40        LOGE("setCamera called in an invalid state(%d)", mCurrentState);
41        return INVALID_OPERATION;
42    }
43
44    status_t ret = mMediaRecorder->setCamera(camera, proxy);
45    if (OK != ret) {
46        LOGV("setCamera failed: %d", ret);
47        mCurrentState = MEDIA_RECORDER_ERROR;
48        return ret;
49    }
50    return ret;
51}
52
53status_t MediaRecorder::setPreviewSurface(const sp<Surface>& surface)
54{
55    LOGV("setPreviewSurface(%p)", surface.get());
56    if(mMediaRecorder == NULL) {
57        LOGE("media recorder is not initialized yet");
58        return INVALID_OPERATION;
59    }
60    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
61        LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState);
62        return INVALID_OPERATION;
63    }
64    if (!mIsVideoSourceSet) {
65        LOGE("try to set preview surface without setting the video source first");
66        return INVALID_OPERATION;
67    }
68
69    status_t ret = mMediaRecorder->setPreviewSurface(surface);
70    if (OK != ret) {
71        LOGV("setPreviewSurface failed: %d", ret);
72        mCurrentState = MEDIA_RECORDER_ERROR;
73        return ret;
74    }
75    return ret;
76}
77
78status_t MediaRecorder::init()
79{
80    LOGV("init");
81    if(mMediaRecorder == NULL) {
82        LOGE("media recorder is not initialized yet");
83        return INVALID_OPERATION;
84    }
85    if (!(mCurrentState & MEDIA_RECORDER_IDLE)) {
86        LOGE("init called in an invalid state(%d)", mCurrentState);
87        return INVALID_OPERATION;
88    }
89
90    status_t ret = mMediaRecorder->init();
91    if (OK != ret) {
92        LOGV("init failed: %d", ret);
93        mCurrentState = MEDIA_RECORDER_ERROR;
94        return ret;
95    }
96
97    ret = mMediaRecorder->setListener(this);
98    if (OK != ret) {
99        LOGV("setListener failed: %d", ret);
100        mCurrentState = MEDIA_RECORDER_ERROR;
101        return ret;
102    }
103
104    mCurrentState = MEDIA_RECORDER_INITIALIZED;
105    return ret;
106}
107
108status_t MediaRecorder::setVideoSource(int vs)
109{
110    LOGV("setVideoSource(%d)", vs);
111    if(mMediaRecorder == NULL) {
112        LOGE("media recorder is not initialized yet");
113        return INVALID_OPERATION;
114    }
115    if (mIsVideoSourceSet) {
116        LOGE("video source has already been set");
117        return INVALID_OPERATION;
118    }
119    if (mCurrentState & MEDIA_RECORDER_IDLE) {
120        LOGV("Call init() since the media recorder is not initialized yet");
121        status_t ret = init();
122        if (OK != ret) {
123            return ret;
124        }
125    }
126    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
127        LOGE("setVideoSource called in an invalid state(%d)", mCurrentState);
128        return INVALID_OPERATION;
129    }
130
131    // following call is made over the Binder Interface
132    status_t ret = mMediaRecorder->setVideoSource(vs);
133
134    if (OK != ret) {
135        LOGV("setVideoSource failed: %d", ret);
136        mCurrentState = MEDIA_RECORDER_ERROR;
137        return ret;
138    }
139    mIsVideoSourceSet = true;
140    return ret;
141}
142
143status_t MediaRecorder::setAudioSource(int as)
144{
145    LOGV("setAudioSource(%d)", as);
146    if(mMediaRecorder == NULL) {
147        LOGE("media recorder is not initialized yet");
148        return INVALID_OPERATION;
149    }
150    if (mCurrentState & MEDIA_RECORDER_IDLE) {
151        LOGV("Call init() since the media recorder is not initialized yet");
152        status_t ret = init();
153        if (OK != ret) {
154            return ret;
155        }
156    }
157    if (mIsAudioSourceSet) {
158        LOGE("audio source has already been set");
159        return INVALID_OPERATION;
160    }
161    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
162        LOGE("setAudioSource called in an invalid state(%d)", mCurrentState);
163        return INVALID_OPERATION;
164    }
165
166    status_t ret = mMediaRecorder->setAudioSource(as);
167    if (OK != ret) {
168        LOGV("setAudioSource failed: %d", ret);
169        mCurrentState = MEDIA_RECORDER_ERROR;
170        return ret;
171    }
172    mIsAudioSourceSet = true;
173    return ret;
174}
175
176status_t MediaRecorder::setOutputFormat(int of)
177{
178    LOGV("setOutputFormat(%d)", of);
179    if(mMediaRecorder == NULL) {
180        LOGE("media recorder is not initialized yet");
181        return INVALID_OPERATION;
182    }
183    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
184        LOGE("setOutputFormat called in an invalid state: %d", mCurrentState);
185        return INVALID_OPERATION;
186    }
187    if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START && of != OUTPUT_FORMAT_RTP_AVP && of != OUTPUT_FORMAT_MPEG2TS) { //first non-video output format
188        LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of);
189        return INVALID_OPERATION;
190    }
191
192    status_t ret = mMediaRecorder->setOutputFormat(of);
193    if (OK != ret) {
194        LOGE("setOutputFormat failed: %d", ret);
195        mCurrentState = MEDIA_RECORDER_ERROR;
196        return ret;
197    }
198    mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED;
199    return ret;
200}
201
202status_t MediaRecorder::setVideoEncoder(int ve)
203{
204    LOGV("setVideoEncoder(%d)", ve);
205    if(mMediaRecorder == NULL) {
206        LOGE("media recorder is not initialized yet");
207        return INVALID_OPERATION;
208    }
209    if (!mIsVideoSourceSet) {
210        LOGE("try to set the video encoder without setting the video source first");
211        return INVALID_OPERATION;
212    }
213    if (mIsVideoEncoderSet) {
214        LOGE("video encoder has already been set");
215        return INVALID_OPERATION;
216    }
217    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
218        LOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState);
219        return INVALID_OPERATION;
220    }
221
222    status_t ret = mMediaRecorder->setVideoEncoder(ve);
223    if (OK != ret) {
224        LOGV("setVideoEncoder failed: %d", ret);
225        mCurrentState = MEDIA_RECORDER_ERROR;
226        return ret;
227    }
228    mIsVideoEncoderSet = true;
229    return ret;
230}
231
232status_t MediaRecorder::setAudioEncoder(int ae)
233{
234    LOGV("setAudioEncoder(%d)", ae);
235    if(mMediaRecorder == NULL) {
236        LOGE("media recorder is not initialized yet");
237        return INVALID_OPERATION;
238    }
239    if (!mIsAudioSourceSet) {
240        LOGE("try to set the audio encoder without setting the audio source first");
241        return INVALID_OPERATION;
242    }
243    if (mIsAudioEncoderSet) {
244        LOGE("audio encoder has already been set");
245        return INVALID_OPERATION;
246    }
247    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
248        LOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState);
249        return INVALID_OPERATION;
250    }
251
252    status_t ret = mMediaRecorder->setAudioEncoder(ae);
253    if (OK != ret) {
254        LOGV("setAudioEncoder failed: %d", ret);
255        mCurrentState = MEDIA_RECORDER_ERROR;
256        return ret;
257    }
258    mIsAudioEncoderSet = true;
259    return ret;
260}
261
262status_t MediaRecorder::setOutputFile(const char* path)
263{
264    LOGV("setOutputFile(%s)", path);
265    if(mMediaRecorder == NULL) {
266        LOGE("media recorder is not initialized yet");
267        return INVALID_OPERATION;
268    }
269    if (mIsOutputFileSet) {
270        LOGE("output file has already been set");
271        return INVALID_OPERATION;
272    }
273    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
274        LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
275        return INVALID_OPERATION;
276    }
277
278    status_t ret = mMediaRecorder->setOutputFile(path);
279    if (OK != ret) {
280        LOGV("setOutputFile failed: %d", ret);
281        mCurrentState = MEDIA_RECORDER_ERROR;
282        return ret;
283    }
284    mIsOutputFileSet = true;
285    return ret;
286}
287
288status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length)
289{
290    LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
291    if(mMediaRecorder == NULL) {
292        LOGE("media recorder is not initialized yet");
293        return INVALID_OPERATION;
294    }
295    if (mIsOutputFileSet) {
296        LOGE("output file has already been set");
297        return INVALID_OPERATION;
298    }
299    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
300        LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
301        return INVALID_OPERATION;
302    }
303
304    // It appears that if an invalid file descriptor is passed through
305    // binder calls, the server-side of the inter-process function call
306    // is skipped. As a result, the check at the server-side to catch
307    // the invalid file descritpor never gets invoked. This is to workaround
308    // this issue by checking the file descriptor first before passing
309    // it through binder call.
310    if (fd < 0) {
311        LOGE("Invalid file descriptor: %d", fd);
312        return BAD_VALUE;
313    }
314
315    status_t ret = mMediaRecorder->setOutputFile(fd, offset, length);
316    if (OK != ret) {
317        LOGV("setOutputFile failed: %d", ret);
318        mCurrentState = MEDIA_RECORDER_ERROR;
319        return ret;
320    }
321    mIsOutputFileSet = true;
322    return ret;
323}
324
325status_t MediaRecorder::setOutputFileAuxiliary(int fd)
326{
327    LOGV("setOutputFileAuxiliary(%d)", fd);
328    if(mMediaRecorder == NULL) {
329        LOGE("media recorder is not initialized yet");
330        return INVALID_OPERATION;
331    }
332    if (mIsAuxiliaryOutputFileSet) {
333        LOGE("output file has already been set");
334        return INVALID_OPERATION;
335    }
336    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
337        LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
338        return INVALID_OPERATION;
339    }
340
341    status_t ret = mMediaRecorder->setOutputFileAuxiliary(fd);
342    if (OK != ret) {
343        LOGV("setOutputFileAuxiliary failed: %d", ret);
344        mCurrentState = MEDIA_RECORDER_ERROR;
345        return ret;
346    }
347    mIsAuxiliaryOutputFileSet = true;
348    return ret;
349}
350
351status_t MediaRecorder::setVideoSize(int width, int height)
352{
353    LOGV("setVideoSize(%d, %d)", width, height);
354    if(mMediaRecorder == NULL) {
355        LOGE("media recorder is not initialized yet");
356        return INVALID_OPERATION;
357    }
358    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
359        LOGE("setVideoSize called in an invalid state: %d", mCurrentState);
360        return INVALID_OPERATION;
361    }
362    if (!mIsVideoSourceSet) {
363        LOGE("Cannot set video size without setting video source first");
364        return INVALID_OPERATION;
365    }
366
367    status_t ret = mMediaRecorder->setVideoSize(width, height);
368    if (OK != ret) {
369        LOGE("setVideoSize failed: %d", ret);
370        mCurrentState = MEDIA_RECORDER_ERROR;
371        return ret;
372    }
373
374    return ret;
375}
376
377// Query a SurfaceMediaSurface through the Mediaserver, over the
378// binder interface. This is used by the Filter Framework (MeidaEncoder)
379// to get an <ISurfaceTexture> object to hook up to ANativeWindow.
380sp<ISurfaceTexture> MediaRecorder::
381        querySurfaceMediaSourceFromMediaServer()
382{
383    Mutex::Autolock _l(mLock);
384    mSurfaceMediaSource =
385            mMediaRecorder->querySurfaceMediaSource();
386    if (mSurfaceMediaSource == NULL) {
387        LOGE("SurfaceMediaSource could not be initialized!");
388    }
389    return mSurfaceMediaSource;
390}
391
392
393
394status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
395{
396    LOGV("setVideoFrameRate(%d)", frames_per_second);
397    if(mMediaRecorder == NULL) {
398        LOGE("media recorder is not initialized yet");
399        return INVALID_OPERATION;
400    }
401    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
402        LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
403        return INVALID_OPERATION;
404    }
405    if (!mIsVideoSourceSet) {
406        LOGE("Cannot set video frame rate without setting video source first");
407        return INVALID_OPERATION;
408    }
409
410    status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second);
411    if (OK != ret) {
412        LOGE("setVideoFrameRate failed: %d", ret);
413        mCurrentState = MEDIA_RECORDER_ERROR;
414        return ret;
415    }
416    return ret;
417}
418
419status_t MediaRecorder::setParameters(const String8& params) {
420    LOGV("setParameters(%s)", params.string());
421    if(mMediaRecorder == NULL) {
422        LOGE("media recorder is not initialized yet");
423        return INVALID_OPERATION;
424    }
425
426    bool isInvalidState = (mCurrentState &
427                           (MEDIA_RECORDER_PREPARED |
428                            MEDIA_RECORDER_RECORDING |
429                            MEDIA_RECORDER_ERROR));
430    if (isInvalidState) {
431        LOGE("setParameters is called in an invalid state: %d", mCurrentState);
432        return INVALID_OPERATION;
433    }
434
435    status_t ret = mMediaRecorder->setParameters(params);
436    if (OK != ret) {
437        LOGE("setParameters(%s) failed: %d", params.string(), ret);
438        // Do not change our current state to MEDIA_RECORDER_ERROR, failures
439        // of the only currently supported parameters, "max-duration" and
440        // "max-filesize" are _not_ fatal.
441    }
442
443    return ret;
444}
445
446status_t MediaRecorder::prepare()
447{
448    LOGV("prepare");
449    if(mMediaRecorder == NULL) {
450        LOGE("media recorder is not initialized yet");
451        return INVALID_OPERATION;
452    }
453    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
454        LOGE("prepare called in an invalid state: %d", mCurrentState);
455        return INVALID_OPERATION;
456    }
457    if (mIsAudioSourceSet != mIsAudioEncoderSet) {
458        if (mIsAudioSourceSet) {
459            LOGE("audio source is set, but audio encoder is not set");
460        } else {  // must not happen, since setAudioEncoder checks this already
461            LOGE("audio encoder is set, but audio source is not set");
462        }
463        return INVALID_OPERATION;
464    }
465
466    if (mIsVideoSourceSet != mIsVideoEncoderSet) {
467        if (mIsVideoSourceSet) {
468            LOGE("video source is set, but video encoder is not set");
469        } else {  // must not happen, since setVideoEncoder checks this already
470            LOGE("video encoder is set, but video source is not set");
471        }
472        return INVALID_OPERATION;
473    }
474
475    status_t ret = mMediaRecorder->prepare();
476    if (OK != ret) {
477        LOGE("prepare failed: %d", ret);
478        mCurrentState = MEDIA_RECORDER_ERROR;
479        return ret;
480    }
481    mCurrentState = MEDIA_RECORDER_PREPARED;
482    return ret;
483}
484
485status_t MediaRecorder::getMaxAmplitude(int* max)
486{
487    LOGV("getMaxAmplitude");
488    if(mMediaRecorder == NULL) {
489        LOGE("media recorder is not initialized yet");
490        return INVALID_OPERATION;
491    }
492    if (mCurrentState & MEDIA_RECORDER_ERROR) {
493        LOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState);
494        return INVALID_OPERATION;
495    }
496
497    status_t ret = mMediaRecorder->getMaxAmplitude(max);
498    if (OK != ret) {
499        LOGE("getMaxAmplitude failed: %d", ret);
500        mCurrentState = MEDIA_RECORDER_ERROR;
501        return ret;
502    }
503    return ret;
504}
505
506status_t MediaRecorder::start()
507{
508    LOGV("start");
509    if (mMediaRecorder == NULL) {
510        LOGE("media recorder is not initialized yet");
511        return INVALID_OPERATION;
512    }
513    if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) {
514        LOGE("start called in an invalid state: %d", mCurrentState);
515        return INVALID_OPERATION;
516    }
517
518    status_t ret = mMediaRecorder->start();
519    if (OK != ret) {
520        LOGE("start failed: %d", ret);
521        mCurrentState = MEDIA_RECORDER_ERROR;
522        return ret;
523    }
524    mCurrentState = MEDIA_RECORDER_RECORDING;
525    return ret;
526}
527
528status_t MediaRecorder::stop()
529{
530    LOGV("stop");
531    if (mMediaRecorder == NULL) {
532        LOGE("media recorder is not initialized yet");
533        return INVALID_OPERATION;
534    }
535    if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) {
536        LOGE("stop called in an invalid state: %d", mCurrentState);
537        return INVALID_OPERATION;
538    }
539
540    status_t ret = mMediaRecorder->stop();
541    if (OK != ret) {
542        LOGE("stop failed: %d", ret);
543        mCurrentState = MEDIA_RECORDER_ERROR;
544        return ret;
545    }
546
547    // FIXME:
548    // stop and reset are semantically different.
549    // We treat them the same for now, and will change this in the future.
550    doCleanUp();
551    mCurrentState = MEDIA_RECORDER_IDLE;
552    return ret;
553}
554
555// Reset should be OK in any state
556status_t MediaRecorder::reset()
557{
558    LOGV("reset");
559    if (mMediaRecorder == NULL) {
560        LOGE("media recorder is not initialized yet");
561        return INVALID_OPERATION;
562    }
563
564    doCleanUp();
565    status_t ret = UNKNOWN_ERROR;
566    switch(mCurrentState) {
567        case MEDIA_RECORDER_IDLE:
568            ret = OK;
569            break;
570
571        case MEDIA_RECORDER_RECORDING:
572        case MEDIA_RECORDER_DATASOURCE_CONFIGURED:
573        case MEDIA_RECORDER_PREPARED:
574        case MEDIA_RECORDER_ERROR: {
575            ret = doReset();
576            if (OK != ret) {
577               return ret;  // No need to continue
578            }
579        }  // Intentional fall through
580        case MEDIA_RECORDER_INITIALIZED:
581            ret = close();
582            break;
583
584        default: {
585            LOGE("Unexpected non-existing state: %d", mCurrentState);
586            break;
587        }
588    }
589    return ret;
590}
591
592status_t MediaRecorder::close()
593{
594    LOGV("close");
595    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
596        LOGE("close called in an invalid state: %d", mCurrentState);
597        return INVALID_OPERATION;
598    }
599    status_t ret = mMediaRecorder->close();
600    if (OK != ret) {
601        LOGE("close failed: %d", ret);
602        mCurrentState = MEDIA_RECORDER_ERROR;
603        return UNKNOWN_ERROR;
604    } else {
605        mCurrentState = MEDIA_RECORDER_IDLE;
606    }
607    return ret;
608}
609
610status_t MediaRecorder::doReset()
611{
612    LOGV("doReset");
613    status_t ret = mMediaRecorder->reset();
614    if (OK != ret) {
615        LOGE("doReset failed: %d", ret);
616        mCurrentState = MEDIA_RECORDER_ERROR;
617        return ret;
618    } else {
619        mCurrentState = MEDIA_RECORDER_INITIALIZED;
620    }
621    return ret;
622}
623
624void MediaRecorder::doCleanUp()
625{
626    LOGV("doCleanUp");
627    mIsAudioSourceSet  = false;
628    mIsVideoSourceSet  = false;
629    mIsAudioEncoderSet = false;
630    mIsVideoEncoderSet = false;
631    mIsOutputFileSet   = false;
632    mIsAuxiliaryOutputFileSet = false;
633}
634
635// Release should be OK in any state
636status_t MediaRecorder::release()
637{
638    LOGV("release");
639    if (mMediaRecorder != NULL) {
640        return mMediaRecorder->release();
641    }
642    return INVALID_OPERATION;
643}
644
645MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL)
646{
647    LOGV("constructor");
648
649    const sp<IMediaPlayerService>& service(getMediaPlayerService());
650    if (service != NULL) {
651        mMediaRecorder = service->createMediaRecorder(getpid());
652    }
653    if (mMediaRecorder != NULL) {
654        mCurrentState = MEDIA_RECORDER_IDLE;
655    }
656
657
658    doCleanUp();
659}
660
661status_t MediaRecorder::initCheck()
662{
663    return mMediaRecorder != 0 ? NO_ERROR : NO_INIT;
664}
665
666MediaRecorder::~MediaRecorder()
667{
668    LOGV("destructor");
669    if (mMediaRecorder != NULL) {
670        mMediaRecorder.clear();
671    }
672
673    if (mSurfaceMediaSource != NULL) {
674        mSurfaceMediaSource.clear();
675    }
676}
677
678status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
679{
680    LOGV("setListener");
681    Mutex::Autolock _l(mLock);
682    mListener = listener;
683
684    return NO_ERROR;
685}
686
687void MediaRecorder::notify(int msg, int ext1, int ext2)
688{
689    LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
690
691    sp<MediaRecorderListener> listener;
692    mLock.lock();
693    listener = mListener;
694    mLock.unlock();
695
696    if (listener != NULL) {
697        Mutex::Autolock _l(mNotifyLock);
698        LOGV("callback application");
699        listener->notify(msg, ext1, ext2);
700        LOGV("back from callback");
701    }
702}
703
704void MediaRecorder::died()
705{
706    LOGV("died");
707    notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
708}
709
710}; // namespace android
711